1fe723b9aSBill Schmidt //===----------- PPCVSXSwapRemoval.cpp - Remove VSX LE Swaps -------------===// 2fe723b9aSBill Schmidt // 3fe723b9aSBill Schmidt // The LLVM Compiler Infrastructure 4fe723b9aSBill Schmidt // 5fe723b9aSBill Schmidt // This file is distributed under the University of Illinois Open Source 6fe723b9aSBill Schmidt // License. See LICENSE.TXT for details. 7fe723b9aSBill Schmidt // 8fe723b9aSBill Schmidt //===---------------------------------------------------------------------===// 9fe723b9aSBill Schmidt // 10fe723b9aSBill Schmidt // This pass analyzes vector computations and removes unnecessary 11fe723b9aSBill Schmidt // doubleword swaps (xxswapd instructions). This pass is performed 12fe723b9aSBill Schmidt // only for little-endian VSX code generation. 13fe723b9aSBill Schmidt // 14fe723b9aSBill Schmidt // For this specific case, loads and stores of v4i32, v4f32, v2i64, 15fe723b9aSBill Schmidt // and v2f64 vectors are inefficient. These are implemented using 16fe723b9aSBill Schmidt // the lxvd2x and stxvd2x instructions, which invert the order of 17fe723b9aSBill Schmidt // doublewords in a vector register. Thus code generation inserts 18fe723b9aSBill Schmidt // an xxswapd after each such load, and prior to each such store. 19fe723b9aSBill Schmidt // 20fe723b9aSBill Schmidt // The extra xxswapd instructions reduce performance. The purpose 21fe723b9aSBill Schmidt // of this pass is to reduce the number of xxswapd instructions 22fe723b9aSBill Schmidt // required for correctness. 23fe723b9aSBill Schmidt // 24fe723b9aSBill Schmidt // The primary insight is that much code that operates on vectors 25fe723b9aSBill Schmidt // does not care about the relative order of elements in a register, 26fe723b9aSBill Schmidt // so long as the correct memory order is preserved. If we have a 27fe723b9aSBill Schmidt // computation where all input values are provided by lxvd2x/xxswapd, 28fe723b9aSBill Schmidt // all outputs are stored using xxswapd/lxvd2x, and all intermediate 29fe723b9aSBill Schmidt // computations are lane-insensitive (independent of element order), 30fe723b9aSBill Schmidt // then all the xxswapd instructions associated with the loads and 31fe723b9aSBill Schmidt // stores may be removed without changing observable semantics. 32fe723b9aSBill Schmidt // 33fe723b9aSBill Schmidt // This pass uses standard equivalence class infrastructure to create 34fe723b9aSBill Schmidt // maximal webs of computations fitting the above description. Each 35fe723b9aSBill Schmidt // such web is then optimized by removing its unnecessary xxswapd 36fe723b9aSBill Schmidt // instructions. 37fe723b9aSBill Schmidt // 38fe723b9aSBill Schmidt // There are some lane-sensitive operations for which we can still 39fe723b9aSBill Schmidt // permit the optimization, provided we modify those operations 40fe723b9aSBill Schmidt // accordingly. Such operations are identified as using "special 41fe723b9aSBill Schmidt // handling" within this module. 42fe723b9aSBill Schmidt // 43fe723b9aSBill Schmidt //===---------------------------------------------------------------------===// 44fe723b9aSBill Schmidt 45fe723b9aSBill Schmidt #include "PPCInstrInfo.h" 46fe723b9aSBill Schmidt #include "PPC.h" 47fe723b9aSBill Schmidt #include "PPCInstrBuilder.h" 48fe723b9aSBill Schmidt #include "PPCTargetMachine.h" 49fe723b9aSBill Schmidt #include "llvm/ADT/DenseMap.h" 50fe723b9aSBill Schmidt #include "llvm/ADT/EquivalenceClasses.h" 51fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineFunctionPass.h" 52fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineInstrBuilder.h" 53fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineRegisterInfo.h" 54fe723b9aSBill Schmidt #include "llvm/Support/Debug.h" 55fe723b9aSBill Schmidt #include "llvm/Support/Format.h" 56fe723b9aSBill Schmidt #include "llvm/Support/raw_ostream.h" 57fe723b9aSBill Schmidt 58fe723b9aSBill Schmidt using namespace llvm; 59fe723b9aSBill Schmidt 60fe723b9aSBill Schmidt #define DEBUG_TYPE "ppc-vsx-swaps" 61fe723b9aSBill Schmidt 62fe723b9aSBill Schmidt namespace llvm { 63fe723b9aSBill Schmidt void initializePPCVSXSwapRemovalPass(PassRegistry&); 64fe723b9aSBill Schmidt } 65fe723b9aSBill Schmidt 66fe723b9aSBill Schmidt namespace { 67fe723b9aSBill Schmidt 68fe723b9aSBill Schmidt // A PPCVSXSwapEntry is created for each machine instruction that 69fe723b9aSBill Schmidt // is relevant to a vector computation. 70fe723b9aSBill Schmidt struct PPCVSXSwapEntry { 71fe723b9aSBill Schmidt // Pointer to the instruction. 72fe723b9aSBill Schmidt MachineInstr *VSEMI; 73fe723b9aSBill Schmidt 74fe723b9aSBill Schmidt // Unique ID (position in the swap vector). 75fe723b9aSBill Schmidt int VSEId; 76fe723b9aSBill Schmidt 77fe723b9aSBill Schmidt // Attributes of this node. 78fe723b9aSBill Schmidt unsigned int IsLoad : 1; 79fe723b9aSBill Schmidt unsigned int IsStore : 1; 80fe723b9aSBill Schmidt unsigned int IsSwap : 1; 81fe723b9aSBill Schmidt unsigned int MentionsPhysVR : 1; 82fe723b9aSBill Schmidt unsigned int HasImplicitSubreg : 1; 83fe723b9aSBill Schmidt unsigned int IsSwappable : 1; 84fe723b9aSBill Schmidt unsigned int SpecialHandling : 3; 85fe723b9aSBill Schmidt unsigned int WebRejected : 1; 86fe723b9aSBill Schmidt unsigned int WillRemove : 1; 87fe723b9aSBill Schmidt }; 88fe723b9aSBill Schmidt 89fe723b9aSBill Schmidt enum SHValues { 90fe723b9aSBill Schmidt SH_NONE = 0, 91fe723b9aSBill Schmidt SH_EXTRACT, 92fe723b9aSBill Schmidt SH_INSERT, 93fe723b9aSBill Schmidt SH_NOSWAP_LD, 94fe723b9aSBill Schmidt SH_NOSWAP_ST, 95fe723b9aSBill Schmidt SH_SPLAT 96fe723b9aSBill Schmidt }; 97fe723b9aSBill Schmidt 98fe723b9aSBill Schmidt struct PPCVSXSwapRemoval : public MachineFunctionPass { 99fe723b9aSBill Schmidt 100fe723b9aSBill Schmidt static char ID; 101fe723b9aSBill Schmidt const PPCInstrInfo *TII; 102fe723b9aSBill Schmidt MachineFunction *MF; 103fe723b9aSBill Schmidt MachineRegisterInfo *MRI; 104fe723b9aSBill Schmidt 105fe723b9aSBill Schmidt // Swap entries are allocated in a vector for better performance. 106fe723b9aSBill Schmidt std::vector<PPCVSXSwapEntry> SwapVector; 107fe723b9aSBill Schmidt 108fe723b9aSBill Schmidt // A mapping is maintained between machine instructions and 109fe723b9aSBill Schmidt // their swap entries. The key is the address of the MI. 110fe723b9aSBill Schmidt DenseMap<MachineInstr*, int> SwapMap; 111fe723b9aSBill Schmidt 112fe723b9aSBill Schmidt // Equivalence classes are used to gather webs of related computation. 113fe723b9aSBill Schmidt // Swap entries are represented by their VSEId fields. 114fe723b9aSBill Schmidt EquivalenceClasses<int> *EC; 115fe723b9aSBill Schmidt 116fe723b9aSBill Schmidt PPCVSXSwapRemoval() : MachineFunctionPass(ID) { 117fe723b9aSBill Schmidt initializePPCVSXSwapRemovalPass(*PassRegistry::getPassRegistry()); 118fe723b9aSBill Schmidt } 119fe723b9aSBill Schmidt 120fe723b9aSBill Schmidt private: 121fe723b9aSBill Schmidt // Initialize data structures. 122fe723b9aSBill Schmidt void initialize(MachineFunction &MFParm); 123fe723b9aSBill Schmidt 124fe723b9aSBill Schmidt // Walk the machine instructions to gather vector usage information. 125fe723b9aSBill Schmidt // Return true iff vector mentions are present. 126fe723b9aSBill Schmidt bool gatherVectorInstructions(); 127fe723b9aSBill Schmidt 128fe723b9aSBill Schmidt // Add an entry to the swap vector and swap map. 129fe723b9aSBill Schmidt int addSwapEntry(MachineInstr *MI, PPCVSXSwapEntry &SwapEntry); 130fe723b9aSBill Schmidt 131fe723b9aSBill Schmidt // Hunt backwards through COPY and SUBREG_TO_REG chains for a 132fe723b9aSBill Schmidt // source register. VecIdx indicates the swap vector entry to 133fe723b9aSBill Schmidt // mark as mentioning a physical register if the search leads 134fe723b9aSBill Schmidt // to one. 135fe723b9aSBill Schmidt unsigned lookThruCopyLike(unsigned SrcReg, unsigned VecIdx); 136fe723b9aSBill Schmidt 137fe723b9aSBill Schmidt // Generate equivalence classes for related computations (webs). 138fe723b9aSBill Schmidt void formWebs(); 139fe723b9aSBill Schmidt 140fe723b9aSBill Schmidt // Analyze webs and determine those that cannot be optimized. 141fe723b9aSBill Schmidt void recordUnoptimizableWebs(); 142fe723b9aSBill Schmidt 143fe723b9aSBill Schmidt // Record which swap instructions can be safely removed. 144fe723b9aSBill Schmidt void markSwapsForRemoval(); 145fe723b9aSBill Schmidt 146fe723b9aSBill Schmidt // Remove swaps and update other instructions requiring special 147fe723b9aSBill Schmidt // handling. Return true iff any changes are made. 148fe723b9aSBill Schmidt bool removeSwaps(); 149fe723b9aSBill Schmidt 150fe723b9aSBill Schmidt // Update instructions requiring special handling. 151fe723b9aSBill Schmidt void handleSpecialSwappables(int EntryIdx); 152fe723b9aSBill Schmidt 153fe723b9aSBill Schmidt // Dump a description of the entries in the swap vector. 154fe723b9aSBill Schmidt void dumpSwapVector(); 155fe723b9aSBill Schmidt 156fe723b9aSBill Schmidt // Return true iff the given register is in the given class. 157fe723b9aSBill Schmidt bool isRegInClass(unsigned Reg, const TargetRegisterClass *RC) { 158fe723b9aSBill Schmidt if (TargetRegisterInfo::isVirtualRegister(Reg)) 159fe723b9aSBill Schmidt return RC->hasSubClassEq(MRI->getRegClass(Reg)); 160fe723b9aSBill Schmidt if (RC->contains(Reg)) 161fe723b9aSBill Schmidt return true; 162fe723b9aSBill Schmidt return false; 163fe723b9aSBill Schmidt } 164fe723b9aSBill Schmidt 165fe723b9aSBill Schmidt // Return true iff the given register is a full vector register. 166fe723b9aSBill Schmidt bool isVecReg(unsigned Reg) { 167fe723b9aSBill Schmidt return (isRegInClass(Reg, &PPC::VSRCRegClass) || 168fe723b9aSBill Schmidt isRegInClass(Reg, &PPC::VRRCRegClass)); 169fe723b9aSBill Schmidt } 170fe723b9aSBill Schmidt 171fe723b9aSBill Schmidt public: 172fe723b9aSBill Schmidt // Main entry point for this pass. 173fe723b9aSBill Schmidt bool runOnMachineFunction(MachineFunction &MF) override { 174fe723b9aSBill Schmidt // If we don't have VSX on the subtarget, don't do anything. 175fe723b9aSBill Schmidt const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>(); 176fe723b9aSBill Schmidt if (!STI.hasVSX()) 177fe723b9aSBill Schmidt return false; 178fe723b9aSBill Schmidt 179fe723b9aSBill Schmidt bool Changed = false; 180fe723b9aSBill Schmidt initialize(MF); 181fe723b9aSBill Schmidt 182fe723b9aSBill Schmidt if (gatherVectorInstructions()) { 183fe723b9aSBill Schmidt formWebs(); 184fe723b9aSBill Schmidt recordUnoptimizableWebs(); 185fe723b9aSBill Schmidt markSwapsForRemoval(); 186fe723b9aSBill Schmidt Changed = removeSwaps(); 187fe723b9aSBill Schmidt } 188fe723b9aSBill Schmidt 189fe723b9aSBill Schmidt // FIXME: See the allocation of EC in initialize(). 190fe723b9aSBill Schmidt delete EC; 191fe723b9aSBill Schmidt return Changed; 192fe723b9aSBill Schmidt } 193fe723b9aSBill Schmidt }; 194fe723b9aSBill Schmidt 195fe723b9aSBill Schmidt // Initialize data structures for this pass. In particular, clear the 196fe723b9aSBill Schmidt // swap vector and allocate the equivalence class mapping before 197fe723b9aSBill Schmidt // processing each function. 198fe723b9aSBill Schmidt void PPCVSXSwapRemoval::initialize(MachineFunction &MFParm) { 199fe723b9aSBill Schmidt MF = &MFParm; 200fe723b9aSBill Schmidt MRI = &MF->getRegInfo(); 201fe723b9aSBill Schmidt TII = static_cast<const PPCInstrInfo*>(MF->getSubtarget().getInstrInfo()); 202fe723b9aSBill Schmidt 203fe723b9aSBill Schmidt // An initial vector size of 256 appears to work well in practice. 204fe723b9aSBill Schmidt // Small/medium functions with vector content tend not to incur a 205fe723b9aSBill Schmidt // reallocation at this size. Three of the vector tests in 206fe723b9aSBill Schmidt // projects/test-suite reallocate, which seems like a reasonable rate. 207fe723b9aSBill Schmidt const int InitialVectorSize(256); 208fe723b9aSBill Schmidt SwapVector.clear(); 209fe723b9aSBill Schmidt SwapVector.reserve(InitialVectorSize); 210fe723b9aSBill Schmidt 211fe723b9aSBill Schmidt // FIXME: Currently we allocate EC each time because we don't have 212fe723b9aSBill Schmidt // access to the set representation on which to call clear(). Should 213fe723b9aSBill Schmidt // consider adding a clear() method to the EquivalenceClasses class. 214fe723b9aSBill Schmidt EC = new EquivalenceClasses<int>; 215fe723b9aSBill Schmidt } 216fe723b9aSBill Schmidt 217fe723b9aSBill Schmidt // Create an entry in the swap vector for each instruction that mentions 218fe723b9aSBill Schmidt // a full vector register, recording various characteristics of the 219fe723b9aSBill Schmidt // instructions there. 220fe723b9aSBill Schmidt bool PPCVSXSwapRemoval::gatherVectorInstructions() { 221fe723b9aSBill Schmidt bool RelevantFunction = false; 222fe723b9aSBill Schmidt 223fe723b9aSBill Schmidt for (MachineBasicBlock &MBB : *MF) { 224fe723b9aSBill Schmidt for (MachineInstr &MI : MBB) { 225fe723b9aSBill Schmidt 226fe723b9aSBill Schmidt bool RelevantInstr = false; 227fe723b9aSBill Schmidt bool ImplicitSubreg = false; 228fe723b9aSBill Schmidt 229fe723b9aSBill Schmidt for (const MachineOperand &MO : MI.operands()) { 230fe723b9aSBill Schmidt if (!MO.isReg()) 231fe723b9aSBill Schmidt continue; 232fe723b9aSBill Schmidt unsigned Reg = MO.getReg(); 233fe723b9aSBill Schmidt if (isVecReg(Reg)) { 234fe723b9aSBill Schmidt RelevantInstr = true; 235fe723b9aSBill Schmidt if (MO.getSubReg() != 0) 236fe723b9aSBill Schmidt ImplicitSubreg = true; 237fe723b9aSBill Schmidt break; 238fe723b9aSBill Schmidt } 239fe723b9aSBill Schmidt } 240fe723b9aSBill Schmidt 241fe723b9aSBill Schmidt if (!RelevantInstr) 242fe723b9aSBill Schmidt continue; 243fe723b9aSBill Schmidt 244fe723b9aSBill Schmidt RelevantFunction = true; 245fe723b9aSBill Schmidt 246fe723b9aSBill Schmidt // Create a SwapEntry initialized to zeros, then fill in the 247fe723b9aSBill Schmidt // instruction and ID fields before pushing it to the back 248fe723b9aSBill Schmidt // of the swap vector. 249fe723b9aSBill Schmidt PPCVSXSwapEntry SwapEntry{}; 250fe723b9aSBill Schmidt int VecIdx = addSwapEntry(&MI, SwapEntry); 251fe723b9aSBill Schmidt 252fe723b9aSBill Schmidt if (ImplicitSubreg) 253fe723b9aSBill Schmidt SwapVector[VecIdx].HasImplicitSubreg = 1; 254fe723b9aSBill Schmidt 255fe723b9aSBill Schmidt switch(MI.getOpcode()) { 256fe723b9aSBill Schmidt default: 257fe723b9aSBill Schmidt // Unless noted otherwise, an instruction is considered 258fe723b9aSBill Schmidt // safe for the optimization. There are a large number of 259fe723b9aSBill Schmidt // such true-SIMD instructions (all vector math, logical, 260fe723b9aSBill Schmidt // select, compare, etc.). 261fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 262fe723b9aSBill Schmidt break; 263fe723b9aSBill Schmidt case PPC::XXPERMDI: 264fe723b9aSBill Schmidt // This is a swap if it is of the form XXPERMDI t, s, s, 2. 265fe723b9aSBill Schmidt // Unfortunately, MachineCSE ignores COPY and SUBREG_TO_REG, so we 266fe723b9aSBill Schmidt // can also see XXPERMDI t, SUBREG_TO_REG(s), SUBREG_TO_REG(s), 2, 267fe723b9aSBill Schmidt // for example. We have to look through chains of COPY and 268fe723b9aSBill Schmidt // SUBREG_TO_REG to find the real source value for comparison. 269fe723b9aSBill Schmidt // If the real source value is a physical register, then mark the 270fe723b9aSBill Schmidt // XXPERMDI as mentioning a physical register. 271fe723b9aSBill Schmidt // Any other form of XXPERMDI is lane-sensitive and unsafe 272fe723b9aSBill Schmidt // for the optimization. 273fe723b9aSBill Schmidt if (MI.getOperand(3).getImm() == 2) { 274fe723b9aSBill Schmidt unsigned trueReg1 = lookThruCopyLike(MI.getOperand(1).getReg(), 275fe723b9aSBill Schmidt VecIdx); 276fe723b9aSBill Schmidt unsigned trueReg2 = lookThruCopyLike(MI.getOperand(2).getReg(), 277fe723b9aSBill Schmidt VecIdx); 278fe723b9aSBill Schmidt if (trueReg1 == trueReg2) 279fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 280fe723b9aSBill Schmidt } 281fe723b9aSBill Schmidt break; 282fe723b9aSBill Schmidt case PPC::LVX: 283fe723b9aSBill Schmidt // Non-permuting loads are currently unsafe. We can use special 284fe723b9aSBill Schmidt // handling for this in the future. By not marking these as 285fe723b9aSBill Schmidt // IsSwap, we ensure computations containing them will be rejected 286fe723b9aSBill Schmidt // for now. 287fe723b9aSBill Schmidt SwapVector[VecIdx].IsLoad = 1; 288fe723b9aSBill Schmidt break; 289fe723b9aSBill Schmidt case PPC::LXVD2X: 290fe723b9aSBill Schmidt case PPC::LXVW4X: 291fe723b9aSBill Schmidt // Permuting loads are marked as both load and swap, and are 292fe723b9aSBill Schmidt // safe for optimization. 293fe723b9aSBill Schmidt SwapVector[VecIdx].IsLoad = 1; 294fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 295fe723b9aSBill Schmidt break; 296fe723b9aSBill Schmidt case PPC::STVX: 297fe723b9aSBill Schmidt // Non-permuting stores are currently unsafe. We can use special 298fe723b9aSBill Schmidt // handling for this in the future. By not marking these as 299fe723b9aSBill Schmidt // IsSwap, we ensure computations containing them will be rejected 300fe723b9aSBill Schmidt // for now. 301fe723b9aSBill Schmidt SwapVector[VecIdx].IsStore = 1; 302fe723b9aSBill Schmidt break; 303fe723b9aSBill Schmidt case PPC::STXVD2X: 304fe723b9aSBill Schmidt case PPC::STXVW4X: 305fe723b9aSBill Schmidt // Permuting stores are marked as both store and swap, and are 306fe723b9aSBill Schmidt // safe for optimization. 307fe723b9aSBill Schmidt SwapVector[VecIdx].IsStore = 1; 308fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 309fe723b9aSBill Schmidt break; 310fe723b9aSBill Schmidt case PPC::SUBREG_TO_REG: 311fe723b9aSBill Schmidt // These are fine provided they are moving between full vector 312fe723b9aSBill Schmidt // register classes. For example, the VRs are a subset of the 313fe723b9aSBill Schmidt // VSRs, but each VR and each VSR is a full 128-bit register. 314fe723b9aSBill Schmidt if (isVecReg(MI.getOperand(0).getReg()) && 315fe723b9aSBill Schmidt isVecReg(MI.getOperand(2).getReg())) 316fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 317fe723b9aSBill Schmidt break; 318fe723b9aSBill Schmidt case PPC::COPY: 319fe723b9aSBill Schmidt // These are fine provided they are moving between full vector 320fe723b9aSBill Schmidt // register classes. 321fe723b9aSBill Schmidt if (isVecReg(MI.getOperand(0).getReg()) && 322fe723b9aSBill Schmidt isVecReg(MI.getOperand(1).getReg())) 323fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 324fe723b9aSBill Schmidt break; 325fe723b9aSBill Schmidt case PPC::VSPLTB: 326fe723b9aSBill Schmidt case PPC::VSPLTH: 327fe723b9aSBill Schmidt case PPC::VSPLTW: 328fe723b9aSBill Schmidt // Splats are lane-sensitive, but we can use special handling 329fe723b9aSBill Schmidt // to adjust the source lane for the splat. This is not yet 330fe723b9aSBill Schmidt // implemented. When it is, we need to uncomment the following: 331*5fe2e25fSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 332fe723b9aSBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_SPLAT; 333fe723b9aSBill Schmidt break; 334fe723b9aSBill Schmidt // The presence of the following lane-sensitive operations in a 335fe723b9aSBill Schmidt // web will kill the optimization, at least for now. For these 336fe723b9aSBill Schmidt // we do nothing, causing the optimization to fail. 337fe723b9aSBill Schmidt // FIXME: Some of these could be permitted with special handling, 338fe723b9aSBill Schmidt // and will be phased in as time permits. 339fe723b9aSBill Schmidt // FIXME: There is no simple and maintainable way to express a set 340fe723b9aSBill Schmidt // of opcodes having a common attribute in TableGen. Should this 341fe723b9aSBill Schmidt // change, this is a prime candidate to use such a mechanism. 342fe723b9aSBill Schmidt case PPC::INLINEASM: 343fe723b9aSBill Schmidt case PPC::EXTRACT_SUBREG: 344fe723b9aSBill Schmidt case PPC::INSERT_SUBREG: 345fe723b9aSBill Schmidt case PPC::COPY_TO_REGCLASS: 346fe723b9aSBill Schmidt case PPC::LVEBX: 347fe723b9aSBill Schmidt case PPC::LVEHX: 348fe723b9aSBill Schmidt case PPC::LVEWX: 349fe723b9aSBill Schmidt case PPC::LVSL: 350fe723b9aSBill Schmidt case PPC::LVSR: 351fe723b9aSBill Schmidt case PPC::LVXL: 352fe723b9aSBill Schmidt case PPC::LXVDSX: 353fe723b9aSBill Schmidt case PPC::STVEBX: 354fe723b9aSBill Schmidt case PPC::STVEHX: 355fe723b9aSBill Schmidt case PPC::STVEWX: 356fe723b9aSBill Schmidt case PPC::STVXL: 357fe723b9aSBill Schmidt case PPC::STXSDX: 358fe723b9aSBill Schmidt case PPC::VCIPHER: 359fe723b9aSBill Schmidt case PPC::VCIPHERLAST: 360fe723b9aSBill Schmidt case PPC::VMRGHB: 361fe723b9aSBill Schmidt case PPC::VMRGHH: 362fe723b9aSBill Schmidt case PPC::VMRGHW: 363fe723b9aSBill Schmidt case PPC::VMRGLB: 364fe723b9aSBill Schmidt case PPC::VMRGLH: 365fe723b9aSBill Schmidt case PPC::VMRGLW: 366fe723b9aSBill Schmidt case PPC::VMULESB: 367fe723b9aSBill Schmidt case PPC::VMULESH: 368fe723b9aSBill Schmidt case PPC::VMULESW: 369fe723b9aSBill Schmidt case PPC::VMULEUB: 370fe723b9aSBill Schmidt case PPC::VMULEUH: 371fe723b9aSBill Schmidt case PPC::VMULEUW: 372fe723b9aSBill Schmidt case PPC::VMULOSB: 373fe723b9aSBill Schmidt case PPC::VMULOSH: 374fe723b9aSBill Schmidt case PPC::VMULOSW: 375fe723b9aSBill Schmidt case PPC::VMULOUB: 376fe723b9aSBill Schmidt case PPC::VMULOUH: 377fe723b9aSBill Schmidt case PPC::VMULOUW: 378fe723b9aSBill Schmidt case PPC::VNCIPHER: 379fe723b9aSBill Schmidt case PPC::VNCIPHERLAST: 380fe723b9aSBill Schmidt case PPC::VPERM: 381fe723b9aSBill Schmidt case PPC::VPERMXOR: 382fe723b9aSBill Schmidt case PPC::VPKPX: 383fe723b9aSBill Schmidt case PPC::VPKSHSS: 384fe723b9aSBill Schmidt case PPC::VPKSHUS: 385fe723b9aSBill Schmidt case PPC::VPKSWSS: 386fe723b9aSBill Schmidt case PPC::VPKSWUS: 387fe723b9aSBill Schmidt case PPC::VPKUHUM: 388fe723b9aSBill Schmidt case PPC::VPKUHUS: 389fe723b9aSBill Schmidt case PPC::VPKUWUM: 390fe723b9aSBill Schmidt case PPC::VPKUWUS: 391fe723b9aSBill Schmidt case PPC::VPMSUMB: 392fe723b9aSBill Schmidt case PPC::VPMSUMD: 393fe723b9aSBill Schmidt case PPC::VPMSUMH: 394fe723b9aSBill Schmidt case PPC::VPMSUMW: 395fe723b9aSBill Schmidt case PPC::VRLB: 396fe723b9aSBill Schmidt case PPC::VRLD: 397fe723b9aSBill Schmidt case PPC::VRLH: 398fe723b9aSBill Schmidt case PPC::VRLW: 399fe723b9aSBill Schmidt case PPC::VSBOX: 400fe723b9aSBill Schmidt case PPC::VSHASIGMAD: 401fe723b9aSBill Schmidt case PPC::VSHASIGMAW: 402fe723b9aSBill Schmidt case PPC::VSL: 403fe723b9aSBill Schmidt case PPC::VSLDOI: 404fe723b9aSBill Schmidt case PPC::VSLO: 405fe723b9aSBill Schmidt case PPC::VSR: 406fe723b9aSBill Schmidt case PPC::VSRO: 407fe723b9aSBill Schmidt case PPC::VSUM2SWS: 408fe723b9aSBill Schmidt case PPC::VSUM4SBS: 409fe723b9aSBill Schmidt case PPC::VSUM4SHS: 410fe723b9aSBill Schmidt case PPC::VSUM4UBS: 411fe723b9aSBill Schmidt case PPC::VSUMSWS: 412fe723b9aSBill Schmidt case PPC::VUPKHPX: 413fe723b9aSBill Schmidt case PPC::VUPKHSB: 414fe723b9aSBill Schmidt case PPC::VUPKHSH: 415fe723b9aSBill Schmidt case PPC::VUPKLPX: 416fe723b9aSBill Schmidt case PPC::VUPKLSB: 417fe723b9aSBill Schmidt case PPC::VUPKLSH: 418fe723b9aSBill Schmidt case PPC::XXMRGHW: 419fe723b9aSBill Schmidt case PPC::XXMRGLW: 420fe723b9aSBill Schmidt case PPC::XXSPLTW: 421fe723b9aSBill Schmidt break; 422fe723b9aSBill Schmidt } 423fe723b9aSBill Schmidt } 424fe723b9aSBill Schmidt } 425fe723b9aSBill Schmidt 426fe723b9aSBill Schmidt if (RelevantFunction) { 427fe723b9aSBill Schmidt DEBUG(dbgs() << "Swap vector when first built\n\n"); 428fe723b9aSBill Schmidt dumpSwapVector(); 429fe723b9aSBill Schmidt } 430fe723b9aSBill Schmidt 431fe723b9aSBill Schmidt return RelevantFunction; 432fe723b9aSBill Schmidt } 433fe723b9aSBill Schmidt 434fe723b9aSBill Schmidt // Add an entry to the swap vector and swap map, and make a 435fe723b9aSBill Schmidt // singleton equivalence class for the entry. 436fe723b9aSBill Schmidt int PPCVSXSwapRemoval::addSwapEntry(MachineInstr *MI, 437fe723b9aSBill Schmidt PPCVSXSwapEntry& SwapEntry) { 438fe723b9aSBill Schmidt SwapEntry.VSEMI = MI; 439fe723b9aSBill Schmidt SwapEntry.VSEId = SwapVector.size(); 440fe723b9aSBill Schmidt SwapVector.push_back(SwapEntry); 441fe723b9aSBill Schmidt EC->insert(SwapEntry.VSEId); 442fe723b9aSBill Schmidt SwapMap[MI] = SwapEntry.VSEId; 443fe723b9aSBill Schmidt return SwapEntry.VSEId; 444fe723b9aSBill Schmidt } 445fe723b9aSBill Schmidt 446fe723b9aSBill Schmidt // This is used to find the "true" source register for an 447fe723b9aSBill Schmidt // XXPERMDI instruction, since MachineCSE does not handle the 448fe723b9aSBill Schmidt // "copy-like" operations (Copy and SubregToReg). Returns 449fe723b9aSBill Schmidt // the original SrcReg unless it is the target of a copy-like 450fe723b9aSBill Schmidt // operation, in which case we chain backwards through all 451fe723b9aSBill Schmidt // such operations to the ultimate source register. If a 452fe723b9aSBill Schmidt // physical register is encountered, we stop the search and 453fe723b9aSBill Schmidt // flag the swap entry indicated by VecIdx (the original 454fe723b9aSBill Schmidt // XXPERMDI) as mentioning a physical register. Similarly 455fe723b9aSBill Schmidt // for implicit subregister mentions (which should never 456fe723b9aSBill Schmidt // happen). 457fe723b9aSBill Schmidt unsigned PPCVSXSwapRemoval::lookThruCopyLike(unsigned SrcReg, 458fe723b9aSBill Schmidt unsigned VecIdx) { 459fe723b9aSBill Schmidt MachineInstr *MI = MRI->getVRegDef(SrcReg); 460fe723b9aSBill Schmidt if (!MI->isCopyLike()) 461fe723b9aSBill Schmidt return SrcReg; 462fe723b9aSBill Schmidt 463fe723b9aSBill Schmidt unsigned CopySrcReg, CopySrcSubreg; 464fe723b9aSBill Schmidt if (MI->isCopy()) { 465fe723b9aSBill Schmidt CopySrcReg = MI->getOperand(1).getReg(); 466fe723b9aSBill Schmidt CopySrcSubreg = MI->getOperand(1).getSubReg(); 467fe723b9aSBill Schmidt } else { 468fe723b9aSBill Schmidt assert(MI->isSubregToReg() && "bad opcode for lookThruCopyLike"); 469fe723b9aSBill Schmidt CopySrcReg = MI->getOperand(2).getReg(); 470fe723b9aSBill Schmidt CopySrcSubreg = MI->getOperand(2).getSubReg(); 471fe723b9aSBill Schmidt } 472fe723b9aSBill Schmidt 473fe723b9aSBill Schmidt if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg)) { 474fe723b9aSBill Schmidt SwapVector[VecIdx].MentionsPhysVR = 1; 475fe723b9aSBill Schmidt return CopySrcReg; 476fe723b9aSBill Schmidt } 477fe723b9aSBill Schmidt 478fe723b9aSBill Schmidt if (CopySrcSubreg != 0) { 479fe723b9aSBill Schmidt SwapVector[VecIdx].HasImplicitSubreg = 1; 480fe723b9aSBill Schmidt return CopySrcReg; 481fe723b9aSBill Schmidt } 482fe723b9aSBill Schmidt 483fe723b9aSBill Schmidt return lookThruCopyLike(CopySrcReg, VecIdx); 484fe723b9aSBill Schmidt } 485fe723b9aSBill Schmidt 486fe723b9aSBill Schmidt // Generate equivalence classes for related computations (webs) by 487fe723b9aSBill Schmidt // def-use relationships of virtual registers. Mention of a physical 488fe723b9aSBill Schmidt // register terminates the generation of equivalence classes as this 489fe723b9aSBill Schmidt // indicates a use of a parameter, definition of a return value, use 490fe723b9aSBill Schmidt // of a value returned from a call, or definition of a parameter to a 491fe723b9aSBill Schmidt // call. Computations with physical register mentions are flagged 492fe723b9aSBill Schmidt // as such so their containing webs will not be optimized. 493fe723b9aSBill Schmidt void PPCVSXSwapRemoval::formWebs() { 494fe723b9aSBill Schmidt 495fe723b9aSBill Schmidt DEBUG(dbgs() << "\n*** Forming webs for swap removal ***\n\n"); 496fe723b9aSBill Schmidt 497fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 498fe723b9aSBill Schmidt 499fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 500fe723b9aSBill Schmidt 501fe723b9aSBill Schmidt DEBUG(dbgs() << "\n" << SwapVector[EntryIdx].VSEId << " "); 502fe723b9aSBill Schmidt DEBUG(MI->dump()); 503fe723b9aSBill Schmidt 504fe723b9aSBill Schmidt // It's sufficient to walk vector uses and join them to their unique 505fe723b9aSBill Schmidt // definitions. In addition, check *all* vector register operands 506fe723b9aSBill Schmidt // for physical regs. 507fe723b9aSBill Schmidt for (const MachineOperand &MO : MI->operands()) { 508fe723b9aSBill Schmidt if (!MO.isReg()) 509fe723b9aSBill Schmidt continue; 510fe723b9aSBill Schmidt 511fe723b9aSBill Schmidt unsigned Reg = MO.getReg(); 512fe723b9aSBill Schmidt if (!isVecReg(Reg)) 513fe723b9aSBill Schmidt continue; 514fe723b9aSBill Schmidt 515fe723b9aSBill Schmidt if (!TargetRegisterInfo::isVirtualRegister(Reg)) { 516fe723b9aSBill Schmidt SwapVector[EntryIdx].MentionsPhysVR = 1; 517fe723b9aSBill Schmidt continue; 518fe723b9aSBill Schmidt } 519fe723b9aSBill Schmidt 520fe723b9aSBill Schmidt if (!MO.isUse()) 521fe723b9aSBill Schmidt continue; 522fe723b9aSBill Schmidt 523fe723b9aSBill Schmidt MachineInstr* DefMI = MRI->getVRegDef(Reg); 524fe723b9aSBill Schmidt assert(SwapMap.find(DefMI) != SwapMap.end() && 525fe723b9aSBill Schmidt "Inconsistency: def of vector reg not found in swap map!"); 526fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 527fe723b9aSBill Schmidt (void)EC->unionSets(SwapVector[DefIdx].VSEId, 528fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId); 529fe723b9aSBill Schmidt 530fe723b9aSBill Schmidt DEBUG(dbgs() << format("Unioning %d with %d\n", SwapVector[DefIdx].VSEId, 531fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId)); 532fe723b9aSBill Schmidt DEBUG(dbgs() << " Def: "); 533fe723b9aSBill Schmidt DEBUG(DefMI->dump()); 534fe723b9aSBill Schmidt } 535fe723b9aSBill Schmidt } 536fe723b9aSBill Schmidt } 537fe723b9aSBill Schmidt 538fe723b9aSBill Schmidt // Walk the swap vector entries looking for conditions that prevent their 539fe723b9aSBill Schmidt // containing computations from being optimized. When such conditions are 540fe723b9aSBill Schmidt // found, mark the representative of the computation's equivalence class 541fe723b9aSBill Schmidt // as rejected. 542fe723b9aSBill Schmidt void PPCVSXSwapRemoval::recordUnoptimizableWebs() { 543fe723b9aSBill Schmidt 544fe723b9aSBill Schmidt DEBUG(dbgs() << "\n*** Rejecting webs for swap removal ***\n\n"); 545fe723b9aSBill Schmidt 546fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 547fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 548fe723b9aSBill Schmidt 549fe723b9aSBill Schmidt // Reject webs containing mentions of physical registers or implicit 550fe723b9aSBill Schmidt // subregs, or containing operations that we don't know how to handle 551fe723b9aSBill Schmidt // in a lane-permuted region. 552fe723b9aSBill Schmidt if (SwapVector[EntryIdx].MentionsPhysVR || 553fe723b9aSBill Schmidt SwapVector[EntryIdx].HasImplicitSubreg || 554fe723b9aSBill Schmidt !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) { 555fe723b9aSBill Schmidt 556fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 557fe723b9aSBill Schmidt 558fe723b9aSBill Schmidt DEBUG(dbgs() << 559fe723b9aSBill Schmidt format("Web %d rejected for physreg, subreg, or not swap[pable]\n", 560fe723b9aSBill Schmidt Repr)); 561fe723b9aSBill Schmidt DEBUG(dbgs() << " in " << EntryIdx << ": "); 562fe723b9aSBill Schmidt DEBUG(SwapVector[EntryIdx].VSEMI->dump()); 563fe723b9aSBill Schmidt DEBUG(dbgs() << "\n"); 564fe723b9aSBill Schmidt } 565fe723b9aSBill Schmidt 566fe723b9aSBill Schmidt // Reject webs than contain swapping loads that feed something other 567fe723b9aSBill Schmidt // than a swap instruction. 568fe723b9aSBill Schmidt else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { 569fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 570fe723b9aSBill Schmidt unsigned DefReg = MI->getOperand(0).getReg(); 571fe723b9aSBill Schmidt 572fe723b9aSBill Schmidt // We skip debug instructions in the analysis. (Note that debug 573fe723b9aSBill Schmidt // location information is still maintained by this optimization 574fe723b9aSBill Schmidt // because it remains on the LXVD2X and STXVD2X instructions after 575fe723b9aSBill Schmidt // the XXPERMDIs are removed.) 576fe723b9aSBill Schmidt for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { 577fe723b9aSBill Schmidt int UseIdx = SwapMap[&UseMI]; 578fe723b9aSBill Schmidt 579fe723b9aSBill Schmidt if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad || 580fe723b9aSBill Schmidt SwapVector[UseIdx].IsStore) { 581fe723b9aSBill Schmidt 582fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 583fe723b9aSBill Schmidt 584fe723b9aSBill Schmidt DEBUG(dbgs() << 585fe723b9aSBill Schmidt format("Web %d rejected for load not feeding swap\n", Repr)); 586fe723b9aSBill Schmidt DEBUG(dbgs() << " def " << EntryIdx << ": "); 587fe723b9aSBill Schmidt DEBUG(MI->dump()); 588fe723b9aSBill Schmidt DEBUG(dbgs() << " use " << UseIdx << ": "); 589fe723b9aSBill Schmidt DEBUG(UseMI.dump()); 590fe723b9aSBill Schmidt DEBUG(dbgs() << "\n"); 591fe723b9aSBill Schmidt } 592fe723b9aSBill Schmidt } 593fe723b9aSBill Schmidt 594fe723b9aSBill Schmidt // Reject webs than contain swapping stores that are fed by something 595fe723b9aSBill Schmidt // other than a swap instruction. 596fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { 597fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 598fe723b9aSBill Schmidt unsigned UseReg = MI->getOperand(0).getReg(); 599fe723b9aSBill Schmidt MachineInstr *DefMI = MRI->getVRegDef(UseReg); 600fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 601fe723b9aSBill Schmidt 602fe723b9aSBill Schmidt if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad || 603fe723b9aSBill Schmidt SwapVector[DefIdx].IsStore) { 604fe723b9aSBill Schmidt 605fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 606fe723b9aSBill Schmidt 607fe723b9aSBill Schmidt DEBUG(dbgs() << 608fe723b9aSBill Schmidt format("Web %d rejected for store not fed by swap\n", Repr)); 609fe723b9aSBill Schmidt DEBUG(dbgs() << " def " << DefIdx << ": "); 610fe723b9aSBill Schmidt DEBUG(DefMI->dump()); 611fe723b9aSBill Schmidt DEBUG(dbgs() << " use " << EntryIdx << ": "); 612fe723b9aSBill Schmidt DEBUG(MI->dump()); 613fe723b9aSBill Schmidt DEBUG(dbgs() << "\n"); 614fe723b9aSBill Schmidt } 615fe723b9aSBill Schmidt } 616fe723b9aSBill Schmidt } 617fe723b9aSBill Schmidt 618fe723b9aSBill Schmidt DEBUG(dbgs() << "Swap vector after web analysis:\n\n"); 619fe723b9aSBill Schmidt dumpSwapVector(); 620fe723b9aSBill Schmidt } 621fe723b9aSBill Schmidt 622fe723b9aSBill Schmidt // Walk the swap vector entries looking for swaps fed by permuting loads 623fe723b9aSBill Schmidt // and swaps that feed permuting stores. If the containing computation 624fe723b9aSBill Schmidt // has not been marked rejected, mark each such swap for removal. 625fe723b9aSBill Schmidt // (Removal is delayed in case optimization has disturbed the pattern, 626fe723b9aSBill Schmidt // such that multiple loads feed the same swap, etc.) 627fe723b9aSBill Schmidt void PPCVSXSwapRemoval::markSwapsForRemoval() { 628fe723b9aSBill Schmidt 629fe723b9aSBill Schmidt DEBUG(dbgs() << "\n*** Marking swaps for removal ***\n\n"); 630fe723b9aSBill Schmidt 631fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 632fe723b9aSBill Schmidt 633fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { 634fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 635fe723b9aSBill Schmidt 636fe723b9aSBill Schmidt if (!SwapVector[Repr].WebRejected) { 637fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 638fe723b9aSBill Schmidt unsigned DefReg = MI->getOperand(0).getReg(); 639fe723b9aSBill Schmidt 640fe723b9aSBill Schmidt for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { 641fe723b9aSBill Schmidt int UseIdx = SwapMap[&UseMI]; 642fe723b9aSBill Schmidt SwapVector[UseIdx].WillRemove = 1; 643fe723b9aSBill Schmidt 644fe723b9aSBill Schmidt DEBUG(dbgs() << "Marking swap fed by load for removal: "); 645fe723b9aSBill Schmidt DEBUG(UseMI.dump()); 646fe723b9aSBill Schmidt } 647fe723b9aSBill Schmidt } 648fe723b9aSBill Schmidt 649fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { 650fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 651fe723b9aSBill Schmidt 652fe723b9aSBill Schmidt if (!SwapVector[Repr].WebRejected) { 653fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 654fe723b9aSBill Schmidt unsigned UseReg = MI->getOperand(0).getReg(); 655fe723b9aSBill Schmidt MachineInstr *DefMI = MRI->getVRegDef(UseReg); 656fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 657fe723b9aSBill Schmidt SwapVector[DefIdx].WillRemove = 1; 658fe723b9aSBill Schmidt 659fe723b9aSBill Schmidt DEBUG(dbgs() << "Marking swap feeding store for removal: "); 660fe723b9aSBill Schmidt DEBUG(DefMI->dump()); 661fe723b9aSBill Schmidt } 662fe723b9aSBill Schmidt 663fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsSwappable && 664*5fe2e25fSBill Schmidt SwapVector[EntryIdx].SpecialHandling != 0) { 665*5fe2e25fSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 666*5fe2e25fSBill Schmidt 667*5fe2e25fSBill Schmidt if (!SwapVector[Repr].WebRejected) 668fe723b9aSBill Schmidt handleSpecialSwappables(EntryIdx); 669fe723b9aSBill Schmidt } 670fe723b9aSBill Schmidt } 671*5fe2e25fSBill Schmidt } 672fe723b9aSBill Schmidt 673fe723b9aSBill Schmidt // The identified swap entry requires special handling to allow its 674fe723b9aSBill Schmidt // containing computation to be optimized. Perform that handling 675fe723b9aSBill Schmidt // here. 676fe723b9aSBill Schmidt // FIXME: This code is to be phased in with subsequent patches. 677fe723b9aSBill Schmidt void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { 678*5fe2e25fSBill Schmidt switch (SwapVector[EntryIdx].SpecialHandling) { 679*5fe2e25fSBill Schmidt 680*5fe2e25fSBill Schmidt default: 681*5fe2e25fSBill Schmidt assert(false && "Unexpected special handling type"); 682*5fe2e25fSBill Schmidt break; 683*5fe2e25fSBill Schmidt 684*5fe2e25fSBill Schmidt // For splats based on an index into a vector, add N/2 modulo N 685*5fe2e25fSBill Schmidt // to the index, where N is the number of vector elements. 686*5fe2e25fSBill Schmidt case SHValues::SH_SPLAT: { 687*5fe2e25fSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 688*5fe2e25fSBill Schmidt unsigned NElts; 689*5fe2e25fSBill Schmidt 690*5fe2e25fSBill Schmidt DEBUG(dbgs() << "Changing splat: "); 691*5fe2e25fSBill Schmidt DEBUG(MI->dump()); 692*5fe2e25fSBill Schmidt 693*5fe2e25fSBill Schmidt switch (MI->getOpcode()) { 694*5fe2e25fSBill Schmidt default: 695*5fe2e25fSBill Schmidt assert(false && "Unexpected splat opcode"); 696*5fe2e25fSBill Schmidt case PPC::VSPLTB: NElts = 16; break; 697*5fe2e25fSBill Schmidt case PPC::VSPLTH: NElts = 8; break; 698*5fe2e25fSBill Schmidt case PPC::VSPLTW: NElts = 4; break; 699*5fe2e25fSBill Schmidt } 700*5fe2e25fSBill Schmidt 701*5fe2e25fSBill Schmidt unsigned EltNo = MI->getOperand(1).getImm(); 702*5fe2e25fSBill Schmidt EltNo = (EltNo + NElts / 2) % NElts; 703*5fe2e25fSBill Schmidt MI->getOperand(1).setImm(EltNo); 704*5fe2e25fSBill Schmidt 705*5fe2e25fSBill Schmidt DEBUG(dbgs() << " Into: "); 706*5fe2e25fSBill Schmidt DEBUG(MI->dump()); 707*5fe2e25fSBill Schmidt break; 708*5fe2e25fSBill Schmidt } 709*5fe2e25fSBill Schmidt 710*5fe2e25fSBill Schmidt } 711fe723b9aSBill Schmidt } 712fe723b9aSBill Schmidt 713fe723b9aSBill Schmidt // Walk the swap vector and replace each entry marked for removal with 714fe723b9aSBill Schmidt // a copy operation. 715fe723b9aSBill Schmidt bool PPCVSXSwapRemoval::removeSwaps() { 716fe723b9aSBill Schmidt 717fe723b9aSBill Schmidt DEBUG(dbgs() << "\n*** Removing swaps ***\n\n"); 718fe723b9aSBill Schmidt 719fe723b9aSBill Schmidt bool Changed = false; 720fe723b9aSBill Schmidt 721fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 722fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WillRemove) { 723fe723b9aSBill Schmidt Changed = true; 724fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 725fe723b9aSBill Schmidt MachineBasicBlock *MBB = MI->getParent(); 726fe723b9aSBill Schmidt BuildMI(*MBB, MI, MI->getDebugLoc(), 727fe723b9aSBill Schmidt TII->get(TargetOpcode::COPY), MI->getOperand(0).getReg()) 728fe723b9aSBill Schmidt .addOperand(MI->getOperand(1)); 729fe723b9aSBill Schmidt 730fe723b9aSBill Schmidt DEBUG(dbgs() << format("Replaced %d with copy: ", 731fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId)); 732fe723b9aSBill Schmidt DEBUG(MI->dump()); 733fe723b9aSBill Schmidt 734fe723b9aSBill Schmidt MI->eraseFromParent(); 735fe723b9aSBill Schmidt } 736fe723b9aSBill Schmidt } 737fe723b9aSBill Schmidt 738fe723b9aSBill Schmidt return Changed; 739fe723b9aSBill Schmidt } 740fe723b9aSBill Schmidt 741fe723b9aSBill Schmidt // For debug purposes, dump the contents of the swap vector. 742fe723b9aSBill Schmidt void PPCVSXSwapRemoval::dumpSwapVector() { 743fe723b9aSBill Schmidt 744fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 745fe723b9aSBill Schmidt 746fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 747fe723b9aSBill Schmidt int ID = SwapVector[EntryIdx].VSEId; 748fe723b9aSBill Schmidt 749fe723b9aSBill Schmidt DEBUG(dbgs() << format("%6d", ID)); 750fe723b9aSBill Schmidt DEBUG(dbgs() << format("%6d", EC->getLeaderValue(ID))); 751fe723b9aSBill Schmidt DEBUG(dbgs() << format(" BB#%3d", MI->getParent()->getNumber())); 752fe723b9aSBill Schmidt DEBUG(dbgs() << format(" %14s ", TII->getName(MI->getOpcode()))); 753fe723b9aSBill Schmidt 754fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsLoad) 755fe723b9aSBill Schmidt DEBUG(dbgs() << "load "); 756fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsStore) 757fe723b9aSBill Schmidt DEBUG(dbgs() << "store "); 758fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsSwap) 759fe723b9aSBill Schmidt DEBUG(dbgs() << "swap "); 760fe723b9aSBill Schmidt if (SwapVector[EntryIdx].MentionsPhysVR) 761fe723b9aSBill Schmidt DEBUG(dbgs() << "physreg "); 762fe723b9aSBill Schmidt if (SwapVector[EntryIdx].HasImplicitSubreg) 763fe723b9aSBill Schmidt DEBUG(dbgs() << "implsubreg "); 764fe723b9aSBill Schmidt 765fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsSwappable) { 766fe723b9aSBill Schmidt DEBUG(dbgs() << "swappable "); 767fe723b9aSBill Schmidt switch(SwapVector[EntryIdx].SpecialHandling) { 768fe723b9aSBill Schmidt default: 769fe723b9aSBill Schmidt DEBUG(dbgs() << "special:**unknown**"); 770fe723b9aSBill Schmidt break; 771fe723b9aSBill Schmidt case SH_NONE: 772fe723b9aSBill Schmidt break; 773fe723b9aSBill Schmidt case SH_EXTRACT: 774fe723b9aSBill Schmidt DEBUG(dbgs() << "special:extract "); 775fe723b9aSBill Schmidt break; 776fe723b9aSBill Schmidt case SH_INSERT: 777fe723b9aSBill Schmidt DEBUG(dbgs() << "special:insert "); 778fe723b9aSBill Schmidt break; 779fe723b9aSBill Schmidt case SH_NOSWAP_LD: 780fe723b9aSBill Schmidt DEBUG(dbgs() << "special:load "); 781fe723b9aSBill Schmidt break; 782fe723b9aSBill Schmidt case SH_NOSWAP_ST: 783fe723b9aSBill Schmidt DEBUG(dbgs() << "special:store "); 784fe723b9aSBill Schmidt break; 785fe723b9aSBill Schmidt case SH_SPLAT: 786fe723b9aSBill Schmidt DEBUG(dbgs() << "special:splat "); 787fe723b9aSBill Schmidt break; 788fe723b9aSBill Schmidt } 789fe723b9aSBill Schmidt } 790fe723b9aSBill Schmidt 791fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WebRejected) 792fe723b9aSBill Schmidt DEBUG(dbgs() << "rejected "); 793fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WillRemove) 794fe723b9aSBill Schmidt DEBUG(dbgs() << "remove "); 795fe723b9aSBill Schmidt 796fe723b9aSBill Schmidt DEBUG(dbgs() << "\n"); 797e71db85bSBill Schmidt 798e71db85bSBill Schmidt // For no-asserts builds. 799e71db85bSBill Schmidt (void)MI; 800e71db85bSBill Schmidt (void)ID; 801fe723b9aSBill Schmidt } 802fe723b9aSBill Schmidt 803fe723b9aSBill Schmidt DEBUG(dbgs() << "\n"); 804fe723b9aSBill Schmidt } 805fe723b9aSBill Schmidt 806fe723b9aSBill Schmidt } // end default namespace 807fe723b9aSBill Schmidt 808fe723b9aSBill Schmidt INITIALIZE_PASS_BEGIN(PPCVSXSwapRemoval, DEBUG_TYPE, 809fe723b9aSBill Schmidt "PowerPC VSX Swap Removal", false, false) 810fe723b9aSBill Schmidt INITIALIZE_PASS_END(PPCVSXSwapRemoval, DEBUG_TYPE, 811fe723b9aSBill Schmidt "PowerPC VSX Swap Removal", false, false) 812fe723b9aSBill Schmidt 813fe723b9aSBill Schmidt char PPCVSXSwapRemoval::ID = 0; 814fe723b9aSBill Schmidt FunctionPass* 815fe723b9aSBill Schmidt llvm::createPPCVSXSwapRemovalPass() { return new PPCVSXSwapRemoval(); } 816