1fe723b9aSBill Schmidt //===----------- PPCVSXSwapRemoval.cpp - Remove VSX LE Swaps -------------===// 2fe723b9aSBill Schmidt // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe723b9aSBill Schmidt // 7fe723b9aSBill Schmidt //===---------------------------------------------------------------------===// 8fe723b9aSBill Schmidt // 9fe723b9aSBill Schmidt // This pass analyzes vector computations and removes unnecessary 10fe723b9aSBill Schmidt // doubleword swaps (xxswapd instructions). This pass is performed 11fe723b9aSBill Schmidt // only for little-endian VSX code generation. 12fe723b9aSBill Schmidt // 13fe723b9aSBill Schmidt // For this specific case, loads and stores of v4i32, v4f32, v2i64, 14fe723b9aSBill Schmidt // and v2f64 vectors are inefficient. These are implemented using 15fe723b9aSBill Schmidt // the lxvd2x and stxvd2x instructions, which invert the order of 16fe723b9aSBill Schmidt // doublewords in a vector register. Thus code generation inserts 17fe723b9aSBill Schmidt // an xxswapd after each such load, and prior to each such store. 18fe723b9aSBill Schmidt // 19fe723b9aSBill Schmidt // The extra xxswapd instructions reduce performance. The purpose 20fe723b9aSBill Schmidt // of this pass is to reduce the number of xxswapd instructions 21fe723b9aSBill Schmidt // required for correctness. 22fe723b9aSBill Schmidt // 23fe723b9aSBill Schmidt // The primary insight is that much code that operates on vectors 24fe723b9aSBill Schmidt // does not care about the relative order of elements in a register, 25fe723b9aSBill Schmidt // so long as the correct memory order is preserved. If we have a 26fe723b9aSBill Schmidt // computation where all input values are provided by lxvd2x/xxswapd, 27fe723b9aSBill Schmidt // all outputs are stored using xxswapd/lxvd2x, and all intermediate 28fe723b9aSBill Schmidt // computations are lane-insensitive (independent of element order), 29fe723b9aSBill Schmidt // then all the xxswapd instructions associated with the loads and 30fe723b9aSBill Schmidt // stores may be removed without changing observable semantics. 31fe723b9aSBill Schmidt // 32fe723b9aSBill Schmidt // This pass uses standard equivalence class infrastructure to create 33fe723b9aSBill Schmidt // maximal webs of computations fitting the above description. Each 34fe723b9aSBill Schmidt // such web is then optimized by removing its unnecessary xxswapd 35fe723b9aSBill Schmidt // instructions. 36fe723b9aSBill Schmidt // 37fe723b9aSBill Schmidt // There are some lane-sensitive operations for which we can still 38fe723b9aSBill Schmidt // permit the optimization, provided we modify those operations 39fe723b9aSBill Schmidt // accordingly. Such operations are identified as using "special 40fe723b9aSBill Schmidt // handling" within this module. 41fe723b9aSBill Schmidt // 42fe723b9aSBill Schmidt //===---------------------------------------------------------------------===// 43fe723b9aSBill Schmidt 44fe723b9aSBill Schmidt #include "PPC.h" 45fe723b9aSBill Schmidt #include "PPCInstrBuilder.h" 466bda14b3SChandler Carruth #include "PPCInstrInfo.h" 47fe723b9aSBill Schmidt #include "PPCTargetMachine.h" 48fe723b9aSBill Schmidt #include "llvm/ADT/DenseMap.h" 49fe723b9aSBill Schmidt #include "llvm/ADT/EquivalenceClasses.h" 50fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineFunctionPass.h" 51fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineInstrBuilder.h" 52fe723b9aSBill Schmidt #include "llvm/CodeGen/MachineRegisterInfo.h" 53432a3883SNico Weber #include "llvm/Config/llvm-config.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 { 63fe723b9aSBill Schmidt 64fe723b9aSBill Schmidt // A PPCVSXSwapEntry is created for each machine instruction that 65fe723b9aSBill Schmidt // is relevant to a vector computation. 66fe723b9aSBill Schmidt struct PPCVSXSwapEntry { 67fe723b9aSBill Schmidt // Pointer to the instruction. 68fe723b9aSBill Schmidt MachineInstr *VSEMI; 69fe723b9aSBill Schmidt 70fe723b9aSBill Schmidt // Unique ID (position in the swap vector). 71fe723b9aSBill Schmidt int VSEId; 72fe723b9aSBill Schmidt 73fe723b9aSBill Schmidt // Attributes of this node. 74fe723b9aSBill Schmidt unsigned int IsLoad : 1; 75fe723b9aSBill Schmidt unsigned int IsStore : 1; 76fe723b9aSBill Schmidt unsigned int IsSwap : 1; 77fe723b9aSBill Schmidt unsigned int MentionsPhysVR : 1; 78fe723b9aSBill Schmidt unsigned int IsSwappable : 1; 7915deb803SBill Schmidt unsigned int MentionsPartialVR : 1; 80fe723b9aSBill Schmidt unsigned int SpecialHandling : 3; 81fe723b9aSBill Schmidt unsigned int WebRejected : 1; 82fe723b9aSBill Schmidt unsigned int WillRemove : 1; 83fe723b9aSBill Schmidt }; 84fe723b9aSBill Schmidt 85fe723b9aSBill Schmidt enum SHValues { 86fe723b9aSBill Schmidt SH_NONE = 0, 87fe723b9aSBill Schmidt SH_EXTRACT, 88fe723b9aSBill Schmidt SH_INSERT, 89fe723b9aSBill Schmidt SH_NOSWAP_LD, 90fe723b9aSBill Schmidt SH_NOSWAP_ST, 9115deb803SBill Schmidt SH_SPLAT, 9215deb803SBill Schmidt SH_XXPERMDI, 932be8054bSBill Schmidt SH_COPYWIDEN 94fe723b9aSBill Schmidt }; 95fe723b9aSBill Schmidt 96fe723b9aSBill Schmidt struct PPCVSXSwapRemoval : public MachineFunctionPass { 97fe723b9aSBill Schmidt 98fe723b9aSBill Schmidt static char ID; 99fe723b9aSBill Schmidt const PPCInstrInfo *TII; 100fe723b9aSBill Schmidt MachineFunction *MF; 101fe723b9aSBill Schmidt MachineRegisterInfo *MRI; 102fe723b9aSBill Schmidt 103fe723b9aSBill Schmidt // Swap entries are allocated in a vector for better performance. 104fe723b9aSBill Schmidt std::vector<PPCVSXSwapEntry> SwapVector; 105fe723b9aSBill Schmidt 106fe723b9aSBill Schmidt // A mapping is maintained between machine instructions and 107fe723b9aSBill Schmidt // their swap entries. The key is the address of the MI. 108fe723b9aSBill Schmidt DenseMap<MachineInstr*, int> SwapMap; 109fe723b9aSBill Schmidt 110fe723b9aSBill Schmidt // Equivalence classes are used to gather webs of related computation. 111fe723b9aSBill Schmidt // Swap entries are represented by their VSEId fields. 112fe723b9aSBill Schmidt EquivalenceClasses<int> *EC; 113fe723b9aSBill Schmidt 114fe723b9aSBill Schmidt PPCVSXSwapRemoval() : MachineFunctionPass(ID) { 115fe723b9aSBill Schmidt initializePPCVSXSwapRemovalPass(*PassRegistry::getPassRegistry()); 116fe723b9aSBill Schmidt } 117fe723b9aSBill Schmidt 118fe723b9aSBill Schmidt private: 119fe723b9aSBill Schmidt // Initialize data structures. 120fe723b9aSBill Schmidt void initialize(MachineFunction &MFParm); 121fe723b9aSBill Schmidt 122fe723b9aSBill Schmidt // Walk the machine instructions to gather vector usage information. 123fe723b9aSBill Schmidt // Return true iff vector mentions are present. 124fe723b9aSBill Schmidt bool gatherVectorInstructions(); 125fe723b9aSBill Schmidt 126fe723b9aSBill Schmidt // Add an entry to the swap vector and swap map. 127fe723b9aSBill Schmidt int addSwapEntry(MachineInstr *MI, PPCVSXSwapEntry &SwapEntry); 128fe723b9aSBill Schmidt 129fe723b9aSBill Schmidt // Hunt backwards through COPY and SUBREG_TO_REG chains for a 130fe723b9aSBill Schmidt // source register. VecIdx indicates the swap vector entry to 131fe723b9aSBill Schmidt // mark as mentioning a physical register if the search leads 132fe723b9aSBill Schmidt // to one. 133fe723b9aSBill Schmidt unsigned lookThruCopyLike(unsigned SrcReg, unsigned VecIdx); 134fe723b9aSBill Schmidt 135fe723b9aSBill Schmidt // Generate equivalence classes for related computations (webs). 136fe723b9aSBill Schmidt void formWebs(); 137fe723b9aSBill Schmidt 138fe723b9aSBill Schmidt // Analyze webs and determine those that cannot be optimized. 139fe723b9aSBill Schmidt void recordUnoptimizableWebs(); 140fe723b9aSBill Schmidt 141fe723b9aSBill Schmidt // Record which swap instructions can be safely removed. 142fe723b9aSBill Schmidt void markSwapsForRemoval(); 143fe723b9aSBill Schmidt 144fe723b9aSBill Schmidt // Remove swaps and update other instructions requiring special 145fe723b9aSBill Schmidt // handling. Return true iff any changes are made. 146fe723b9aSBill Schmidt bool removeSwaps(); 147fe723b9aSBill Schmidt 1482be8054bSBill Schmidt // Insert a swap instruction from SrcReg to DstReg at the given 1492be8054bSBill Schmidt // InsertPoint. 1502be8054bSBill Schmidt void insertSwap(MachineInstr *MI, MachineBasicBlock::iterator InsertPoint, 1512be8054bSBill Schmidt unsigned DstReg, unsigned SrcReg); 1522be8054bSBill Schmidt 153fe723b9aSBill Schmidt // Update instructions requiring special handling. 154fe723b9aSBill Schmidt void handleSpecialSwappables(int EntryIdx); 155fe723b9aSBill Schmidt 156fe723b9aSBill Schmidt // Dump a description of the entries in the swap vector. 157fe723b9aSBill Schmidt void dumpSwapVector(); 158fe723b9aSBill Schmidt 159fe723b9aSBill Schmidt // Return true iff the given register is in the given class. 160fe723b9aSBill Schmidt bool isRegInClass(unsigned Reg, const TargetRegisterClass *RC) { 161fe723b9aSBill Schmidt if (TargetRegisterInfo::isVirtualRegister(Reg)) 162fe723b9aSBill Schmidt return RC->hasSubClassEq(MRI->getRegClass(Reg)); 163175a7cbfSAlexander Kornienko return RC->contains(Reg); 164fe723b9aSBill Schmidt } 165fe723b9aSBill Schmidt 166fe723b9aSBill Schmidt // Return true iff the given register is a full vector register. 167fe723b9aSBill Schmidt bool isVecReg(unsigned Reg) { 168fe723b9aSBill Schmidt return (isRegInClass(Reg, &PPC::VSRCRegClass) || 169fe723b9aSBill Schmidt isRegInClass(Reg, &PPC::VRRCRegClass)); 170fe723b9aSBill Schmidt } 171fe723b9aSBill Schmidt 17215deb803SBill Schmidt // Return true iff the given register is a partial vector register. 17315deb803SBill Schmidt bool isScalarVecReg(unsigned Reg) { 17415deb803SBill Schmidt return (isRegInClass(Reg, &PPC::VSFRCRegClass) || 17515deb803SBill Schmidt isRegInClass(Reg, &PPC::VSSRCRegClass)); 17615deb803SBill Schmidt } 17715deb803SBill Schmidt 17815deb803SBill Schmidt // Return true iff the given register mentions all or part of a 17915deb803SBill Schmidt // vector register. Also sets Partial to true if the mention 18015deb803SBill Schmidt // is for just the floating-point register overlap of the register. 18115deb803SBill Schmidt bool isAnyVecReg(unsigned Reg, bool &Partial) { 18215deb803SBill Schmidt if (isScalarVecReg(Reg)) 18315deb803SBill Schmidt Partial = true; 18415deb803SBill Schmidt return isScalarVecReg(Reg) || isVecReg(Reg); 18515deb803SBill Schmidt } 18615deb803SBill Schmidt 187fe723b9aSBill Schmidt public: 188fe723b9aSBill Schmidt // Main entry point for this pass. 189fe723b9aSBill Schmidt bool runOnMachineFunction(MachineFunction &MF) override { 190f1caa283SMatthias Braun if (skipFunction(MF.getFunction())) 191289bd5f6SAndrew Kaylor return false; 192289bd5f6SAndrew Kaylor 193fe723b9aSBill Schmidt // If we don't have VSX on the subtarget, don't do anything. 1943cd1a036SSean Fertile // Also, on Power 9 the load and store ops preserve element order and so 1953cd1a036SSean Fertile // the swaps are not required. 196fe723b9aSBill Schmidt const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>(); 1973cd1a036SSean Fertile if (!STI.hasVSX() || !STI.needsSwapsForVSXMemOps()) 198fe723b9aSBill Schmidt return false; 199fe723b9aSBill Schmidt 200fe723b9aSBill Schmidt bool Changed = false; 201fe723b9aSBill Schmidt initialize(MF); 202fe723b9aSBill Schmidt 203fe723b9aSBill Schmidt if (gatherVectorInstructions()) { 204fe723b9aSBill Schmidt formWebs(); 205fe723b9aSBill Schmidt recordUnoptimizableWebs(); 206fe723b9aSBill Schmidt markSwapsForRemoval(); 207fe723b9aSBill Schmidt Changed = removeSwaps(); 208fe723b9aSBill Schmidt } 209fe723b9aSBill Schmidt 210fe723b9aSBill Schmidt // FIXME: See the allocation of EC in initialize(). 211fe723b9aSBill Schmidt delete EC; 212fe723b9aSBill Schmidt return Changed; 213fe723b9aSBill Schmidt } 214fe723b9aSBill Schmidt }; 215fe723b9aSBill Schmidt 216fe723b9aSBill Schmidt // Initialize data structures for this pass. In particular, clear the 217fe723b9aSBill Schmidt // swap vector and allocate the equivalence class mapping before 218fe723b9aSBill Schmidt // processing each function. 219fe723b9aSBill Schmidt void PPCVSXSwapRemoval::initialize(MachineFunction &MFParm) { 220fe723b9aSBill Schmidt MF = &MFParm; 221fe723b9aSBill Schmidt MRI = &MF->getRegInfo(); 2228ed7cec1SBill Schmidt TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo(); 223fe723b9aSBill Schmidt 224fe723b9aSBill Schmidt // An initial vector size of 256 appears to work well in practice. 225fe723b9aSBill Schmidt // Small/medium functions with vector content tend not to incur a 226fe723b9aSBill Schmidt // reallocation at this size. Three of the vector tests in 227fe723b9aSBill Schmidt // projects/test-suite reallocate, which seems like a reasonable rate. 228fe723b9aSBill Schmidt const int InitialVectorSize(256); 229fe723b9aSBill Schmidt SwapVector.clear(); 230fe723b9aSBill Schmidt SwapVector.reserve(InitialVectorSize); 231fe723b9aSBill Schmidt 232fe723b9aSBill Schmidt // FIXME: Currently we allocate EC each time because we don't have 233fe723b9aSBill Schmidt // access to the set representation on which to call clear(). Should 234fe723b9aSBill Schmidt // consider adding a clear() method to the EquivalenceClasses class. 235fe723b9aSBill Schmidt EC = new EquivalenceClasses<int>; 236fe723b9aSBill Schmidt } 237fe723b9aSBill Schmidt 238fe723b9aSBill Schmidt // Create an entry in the swap vector for each instruction that mentions 239fe723b9aSBill Schmidt // a full vector register, recording various characteristics of the 240fe723b9aSBill Schmidt // instructions there. 241fe723b9aSBill Schmidt bool PPCVSXSwapRemoval::gatherVectorInstructions() { 242fe723b9aSBill Schmidt bool RelevantFunction = false; 243fe723b9aSBill Schmidt 244fe723b9aSBill Schmidt for (MachineBasicBlock &MBB : *MF) { 245fe723b9aSBill Schmidt for (MachineInstr &MI : MBB) { 246fe723b9aSBill Schmidt 247801bf7ebSShiva Chen if (MI.isDebugInstr()) 24832fd189dSBill Schmidt continue; 24932fd189dSBill Schmidt 250fe723b9aSBill Schmidt bool RelevantInstr = false; 25115deb803SBill Schmidt bool Partial = false; 252fe723b9aSBill Schmidt 253fe723b9aSBill Schmidt for (const MachineOperand &MO : MI.operands()) { 254fe723b9aSBill Schmidt if (!MO.isReg()) 255fe723b9aSBill Schmidt continue; 256fe723b9aSBill Schmidt unsigned Reg = MO.getReg(); 25715deb803SBill Schmidt if (isAnyVecReg(Reg, Partial)) { 258fe723b9aSBill Schmidt RelevantInstr = true; 259fe723b9aSBill Schmidt break; 260fe723b9aSBill Schmidt } 261fe723b9aSBill Schmidt } 262fe723b9aSBill Schmidt 263fe723b9aSBill Schmidt if (!RelevantInstr) 264fe723b9aSBill Schmidt continue; 265fe723b9aSBill Schmidt 266fe723b9aSBill Schmidt RelevantFunction = true; 267fe723b9aSBill Schmidt 268fe723b9aSBill Schmidt // Create a SwapEntry initialized to zeros, then fill in the 269fe723b9aSBill Schmidt // instruction and ID fields before pushing it to the back 270fe723b9aSBill Schmidt // of the swap vector. 271fe723b9aSBill Schmidt PPCVSXSwapEntry SwapEntry{}; 272fe723b9aSBill Schmidt int VecIdx = addSwapEntry(&MI, SwapEntry); 273fe723b9aSBill Schmidt 274fe723b9aSBill Schmidt switch(MI.getOpcode()) { 275fe723b9aSBill Schmidt default: 276fe723b9aSBill Schmidt // Unless noted otherwise, an instruction is considered 277fe723b9aSBill Schmidt // safe for the optimization. There are a large number of 278fe723b9aSBill Schmidt // such true-SIMD instructions (all vector math, logical, 27915deb803SBill Schmidt // select, compare, etc.). However, if the instruction 28015deb803SBill Schmidt // mentions a partial vector register and does not have 28115deb803SBill Schmidt // special handling defined, it is not swappable. 28215deb803SBill Schmidt if (Partial) 28315deb803SBill Schmidt SwapVector[VecIdx].MentionsPartialVR = 1; 28415deb803SBill Schmidt else 285fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 286fe723b9aSBill Schmidt break; 2877c691feeSBill Schmidt case PPC::XXPERMDI: { 288fe723b9aSBill Schmidt // This is a swap if it is of the form XXPERMDI t, s, s, 2. 289fe723b9aSBill Schmidt // Unfortunately, MachineCSE ignores COPY and SUBREG_TO_REG, so we 290fe723b9aSBill Schmidt // can also see XXPERMDI t, SUBREG_TO_REG(s), SUBREG_TO_REG(s), 2, 291fe723b9aSBill Schmidt // for example. We have to look through chains of COPY and 292fe723b9aSBill Schmidt // SUBREG_TO_REG to find the real source value for comparison. 293fe723b9aSBill Schmidt // If the real source value is a physical register, then mark the 294fe723b9aSBill Schmidt // XXPERMDI as mentioning a physical register. 2957c691feeSBill Schmidt int immed = MI.getOperand(3).getImm(); 2967c691feeSBill Schmidt if (immed == 2) { 297fe723b9aSBill Schmidt unsigned trueReg1 = lookThruCopyLike(MI.getOperand(1).getReg(), 298fe723b9aSBill Schmidt VecIdx); 299fe723b9aSBill Schmidt unsigned trueReg2 = lookThruCopyLike(MI.getOperand(2).getReg(), 300fe723b9aSBill Schmidt VecIdx); 301fe723b9aSBill Schmidt if (trueReg1 == trueReg2) 302fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 30315deb803SBill Schmidt else { 30415deb803SBill Schmidt // We can still handle these if the two registers are not 30515deb803SBill Schmidt // identical, by adjusting the form of the XXPERMDI. 30615deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 30715deb803SBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; 308fe723b9aSBill Schmidt } 3097c691feeSBill Schmidt // This is a doubleword splat if it is of the form 3107c691feeSBill Schmidt // XXPERMDI t, s, s, 0 or XXPERMDI t, s, s, 3. As above we 3117c691feeSBill Schmidt // must look through chains of copy-likes to find the source 3127c691feeSBill Schmidt // register. We turn off the marking for mention of a physical 3137c691feeSBill Schmidt // register, because splatting it is safe; the optimization 31415deb803SBill Schmidt // will not swap the value in the physical register. Whether 31515deb803SBill Schmidt // or not the two input registers are identical, we can handle 31615deb803SBill Schmidt // these by adjusting the form of the XXPERMDI. 31715deb803SBill Schmidt } else if (immed == 0 || immed == 3) { 31815deb803SBill Schmidt 31915deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 32015deb803SBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; 32115deb803SBill Schmidt 3227c691feeSBill Schmidt unsigned trueReg1 = lookThruCopyLike(MI.getOperand(1).getReg(), 3237c691feeSBill Schmidt VecIdx); 3247c691feeSBill Schmidt unsigned trueReg2 = lookThruCopyLike(MI.getOperand(2).getReg(), 3257c691feeSBill Schmidt VecIdx); 32615deb803SBill Schmidt if (trueReg1 == trueReg2) 3277c691feeSBill Schmidt SwapVector[VecIdx].MentionsPhysVR = 0; 32815deb803SBill Schmidt 32915deb803SBill Schmidt } else { 33015deb803SBill Schmidt // We can still handle these by adjusting the form of the XXPERMDI. 33115deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 33215deb803SBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI; 3337c691feeSBill Schmidt } 334fe723b9aSBill Schmidt break; 3357c691feeSBill Schmidt } 336fe723b9aSBill Schmidt case PPC::LVX: 337fe723b9aSBill Schmidt // Non-permuting loads are currently unsafe. We can use special 338fe723b9aSBill Schmidt // handling for this in the future. By not marking these as 339fe723b9aSBill Schmidt // IsSwap, we ensure computations containing them will be rejected 340fe723b9aSBill Schmidt // for now. 341fe723b9aSBill Schmidt SwapVector[VecIdx].IsLoad = 1; 342fe723b9aSBill Schmidt break; 343fe723b9aSBill Schmidt case PPC::LXVD2X: 344fe723b9aSBill Schmidt case PPC::LXVW4X: 345fe723b9aSBill Schmidt // Permuting loads are marked as both load and swap, and are 346fe723b9aSBill Schmidt // safe for optimization. 347fe723b9aSBill Schmidt SwapVector[VecIdx].IsLoad = 1; 348fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 349fe723b9aSBill Schmidt break; 3502be8054bSBill Schmidt case PPC::LXSDX: 3512be8054bSBill Schmidt case PPC::LXSSPX: 352438bf4a6STony Jiang case PPC::XFLOADf64: 353438bf4a6STony Jiang case PPC::XFLOADf32: 3542be8054bSBill Schmidt // A load of a floating-point value into the high-order half of 3552be8054bSBill Schmidt // a vector register is safe, provided that we introduce a swap 3562be8054bSBill Schmidt // following the load, which will be done by the SUBREG_TO_REG 3572be8054bSBill Schmidt // support. So just mark these as safe. 3582be8054bSBill Schmidt SwapVector[VecIdx].IsLoad = 1; 3592be8054bSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 3602be8054bSBill Schmidt break; 361fe723b9aSBill Schmidt case PPC::STVX: 362fe723b9aSBill Schmidt // Non-permuting stores are currently unsafe. We can use special 363fe723b9aSBill Schmidt // handling for this in the future. By not marking these as 364fe723b9aSBill Schmidt // IsSwap, we ensure computations containing them will be rejected 365fe723b9aSBill Schmidt // for now. 366fe723b9aSBill Schmidt SwapVector[VecIdx].IsStore = 1; 367fe723b9aSBill Schmidt break; 368fe723b9aSBill Schmidt case PPC::STXVD2X: 369fe723b9aSBill Schmidt case PPC::STXVW4X: 370fe723b9aSBill Schmidt // Permuting stores are marked as both store and swap, and are 371fe723b9aSBill Schmidt // safe for optimization. 372fe723b9aSBill Schmidt SwapVector[VecIdx].IsStore = 1; 373fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwap = 1; 374fe723b9aSBill Schmidt break; 375fe723b9aSBill Schmidt case PPC::COPY: 376fe723b9aSBill Schmidt // These are fine provided they are moving between full vector 377fe723b9aSBill Schmidt // register classes. 378fe723b9aSBill Schmidt if (isVecReg(MI.getOperand(0).getReg()) && 379fe723b9aSBill Schmidt isVecReg(MI.getOperand(1).getReg())) 380fe723b9aSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 38115deb803SBill Schmidt // If we have a copy from one scalar floating-point register 38215deb803SBill Schmidt // to another, we can accept this even if it is a physical 38315deb803SBill Schmidt // register. The only way this gets involved is if it feeds 38415deb803SBill Schmidt // a SUBREG_TO_REG, which is handled by introducing a swap. 38515deb803SBill Schmidt else if (isScalarVecReg(MI.getOperand(0).getReg()) && 38615deb803SBill Schmidt isScalarVecReg(MI.getOperand(1).getReg())) 38715deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 388fe723b9aSBill Schmidt break; 38915deb803SBill Schmidt case PPC::SUBREG_TO_REG: { 39015deb803SBill Schmidt // These are fine provided they are moving between full vector 39115deb803SBill Schmidt // register classes. If they are moving from a scalar 39215deb803SBill Schmidt // floating-point class to a vector class, we can handle those 39315deb803SBill Schmidt // as well, provided we introduce a swap. It is generally the 39415deb803SBill Schmidt // case that we will introduce fewer swaps than we remove, but 39515deb803SBill Schmidt // (FIXME) a cost model could be used. However, introduced 39615deb803SBill Schmidt // swaps could potentially be CSEd, so this is not trivial. 39715deb803SBill Schmidt if (isVecReg(MI.getOperand(0).getReg()) && 39815deb803SBill Schmidt isVecReg(MI.getOperand(2).getReg())) 39915deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 40015deb803SBill Schmidt else if (isVecReg(MI.getOperand(0).getReg()) && 40115deb803SBill Schmidt isScalarVecReg(MI.getOperand(2).getReg())) { 40215deb803SBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 4032be8054bSBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_COPYWIDEN; 40415deb803SBill Schmidt } 40515deb803SBill Schmidt break; 40615deb803SBill Schmidt } 407fe723b9aSBill Schmidt case PPC::VSPLTB: 408fe723b9aSBill Schmidt case PPC::VSPLTH: 409fe723b9aSBill Schmidt case PPC::VSPLTW: 4101a2b2f03SNemanja Ivanovic case PPC::XXSPLTW: 411fe723b9aSBill Schmidt // Splats are lane-sensitive, but we can use special handling 4121a2b2f03SNemanja Ivanovic // to adjust the source lane for the splat. 4135fe2e25fSBill Schmidt SwapVector[VecIdx].IsSwappable = 1; 414fe723b9aSBill Schmidt SwapVector[VecIdx].SpecialHandling = SHValues::SH_SPLAT; 415fe723b9aSBill Schmidt break; 416fe723b9aSBill Schmidt // The presence of the following lane-sensitive operations in a 417fe723b9aSBill Schmidt // web will kill the optimization, at least for now. For these 418fe723b9aSBill Schmidt // we do nothing, causing the optimization to fail. 419fe723b9aSBill Schmidt // FIXME: Some of these could be permitted with special handling, 420fe723b9aSBill Schmidt // and will be phased in as time permits. 421fe723b9aSBill Schmidt // FIXME: There is no simple and maintainable way to express a set 422fe723b9aSBill Schmidt // of opcodes having a common attribute in TableGen. Should this 423fe723b9aSBill Schmidt // change, this is a prime candidate to use such a mechanism. 424fe723b9aSBill Schmidt case PPC::INLINEASM: 425*7fcad2f1SNick Desaulniers case PPC::INLINEASM_BR: 426fe723b9aSBill Schmidt case PPC::EXTRACT_SUBREG: 427fe723b9aSBill Schmidt case PPC::INSERT_SUBREG: 428fe723b9aSBill Schmidt case PPC::COPY_TO_REGCLASS: 429fe723b9aSBill Schmidt case PPC::LVEBX: 430fe723b9aSBill Schmidt case PPC::LVEHX: 431fe723b9aSBill Schmidt case PPC::LVEWX: 432fe723b9aSBill Schmidt case PPC::LVSL: 433fe723b9aSBill Schmidt case PPC::LVSR: 434fe723b9aSBill Schmidt case PPC::LVXL: 435fe723b9aSBill Schmidt case PPC::STVEBX: 436fe723b9aSBill Schmidt case PPC::STVEHX: 437fe723b9aSBill Schmidt case PPC::STVEWX: 438fe723b9aSBill Schmidt case PPC::STVXL: 4392be8054bSBill Schmidt // We can handle STXSDX and STXSSPX similarly to LXSDX and LXSSPX, 4402be8054bSBill Schmidt // by adding special handling for narrowing copies as well as 4412be8054bSBill Schmidt // widening ones. However, I've experimented with this, and in 4422be8054bSBill Schmidt // practice we currently do not appear to use STXSDX fed by 4432be8054bSBill Schmidt // a narrowing copy from a full vector register. Since I can't 4442be8054bSBill Schmidt // generate any useful test cases, I've left this alone for now. 445fe723b9aSBill Schmidt case PPC::STXSDX: 4462be8054bSBill Schmidt case PPC::STXSSPX: 447fe723b9aSBill Schmidt case PPC::VCIPHER: 448fe723b9aSBill Schmidt case PPC::VCIPHERLAST: 449fe723b9aSBill Schmidt case PPC::VMRGHB: 450fe723b9aSBill Schmidt case PPC::VMRGHH: 451fe723b9aSBill Schmidt case PPC::VMRGHW: 452fe723b9aSBill Schmidt case PPC::VMRGLB: 453fe723b9aSBill Schmidt case PPC::VMRGLH: 454fe723b9aSBill Schmidt case PPC::VMRGLW: 455fe723b9aSBill Schmidt case PPC::VMULESB: 456fe723b9aSBill Schmidt case PPC::VMULESH: 457fe723b9aSBill Schmidt case PPC::VMULESW: 458fe723b9aSBill Schmidt case PPC::VMULEUB: 459fe723b9aSBill Schmidt case PPC::VMULEUH: 460fe723b9aSBill Schmidt case PPC::VMULEUW: 461fe723b9aSBill Schmidt case PPC::VMULOSB: 462fe723b9aSBill Schmidt case PPC::VMULOSH: 463fe723b9aSBill Schmidt case PPC::VMULOSW: 464fe723b9aSBill Schmidt case PPC::VMULOUB: 465fe723b9aSBill Schmidt case PPC::VMULOUH: 466fe723b9aSBill Schmidt case PPC::VMULOUW: 467fe723b9aSBill Schmidt case PPC::VNCIPHER: 468fe723b9aSBill Schmidt case PPC::VNCIPHERLAST: 469fe723b9aSBill Schmidt case PPC::VPERM: 470fe723b9aSBill Schmidt case PPC::VPERMXOR: 471fe723b9aSBill Schmidt case PPC::VPKPX: 472fe723b9aSBill Schmidt case PPC::VPKSHSS: 473fe723b9aSBill Schmidt case PPC::VPKSHUS: 4745ed84cdbSBill Schmidt case PPC::VPKSDSS: 4755ed84cdbSBill Schmidt case PPC::VPKSDUS: 476fe723b9aSBill Schmidt case PPC::VPKSWSS: 477fe723b9aSBill Schmidt case PPC::VPKSWUS: 4785ed84cdbSBill Schmidt case PPC::VPKUDUM: 4795ed84cdbSBill Schmidt case PPC::VPKUDUS: 480fe723b9aSBill Schmidt case PPC::VPKUHUM: 481fe723b9aSBill Schmidt case PPC::VPKUHUS: 482fe723b9aSBill Schmidt case PPC::VPKUWUM: 483fe723b9aSBill Schmidt case PPC::VPKUWUS: 484fe723b9aSBill Schmidt case PPC::VPMSUMB: 485fe723b9aSBill Schmidt case PPC::VPMSUMD: 486fe723b9aSBill Schmidt case PPC::VPMSUMH: 487fe723b9aSBill Schmidt case PPC::VPMSUMW: 488fe723b9aSBill Schmidt case PPC::VRLB: 489fe723b9aSBill Schmidt case PPC::VRLD: 490fe723b9aSBill Schmidt case PPC::VRLH: 491fe723b9aSBill Schmidt case PPC::VRLW: 492fe723b9aSBill Schmidt case PPC::VSBOX: 493fe723b9aSBill Schmidt case PPC::VSHASIGMAD: 494fe723b9aSBill Schmidt case PPC::VSHASIGMAW: 495fe723b9aSBill Schmidt case PPC::VSL: 496fe723b9aSBill Schmidt case PPC::VSLDOI: 497fe723b9aSBill Schmidt case PPC::VSLO: 498fe723b9aSBill Schmidt case PPC::VSR: 499fe723b9aSBill Schmidt case PPC::VSRO: 500fe723b9aSBill Schmidt case PPC::VSUM2SWS: 501fe723b9aSBill Schmidt case PPC::VSUM4SBS: 502fe723b9aSBill Schmidt case PPC::VSUM4SHS: 503fe723b9aSBill Schmidt case PPC::VSUM4UBS: 504fe723b9aSBill Schmidt case PPC::VSUMSWS: 505fe723b9aSBill Schmidt case PPC::VUPKHPX: 506fe723b9aSBill Schmidt case PPC::VUPKHSB: 507fe723b9aSBill Schmidt case PPC::VUPKHSH: 5085ed84cdbSBill Schmidt case PPC::VUPKHSW: 509fe723b9aSBill Schmidt case PPC::VUPKLPX: 510fe723b9aSBill Schmidt case PPC::VUPKLSB: 511fe723b9aSBill Schmidt case PPC::VUPKLSH: 5125ed84cdbSBill Schmidt case PPC::VUPKLSW: 513fe723b9aSBill Schmidt case PPC::XXMRGHW: 514fe723b9aSBill Schmidt case PPC::XXMRGLW: 51515deb803SBill Schmidt // XXSLDWI could be replaced by a general permute with one of three 51615deb803SBill Schmidt // permute control vectors (for shift values 1, 2, 3). However, 51715deb803SBill Schmidt // VPERM has a more restrictive register class. 51815deb803SBill Schmidt case PPC::XXSLDWI: 51977e34f15SNemanja Ivanovic case PPC::XSCVDPSPN: 52077e34f15SNemanja Ivanovic case PPC::XSCVSPDPN: 521fe723b9aSBill Schmidt break; 522fe723b9aSBill Schmidt } 523fe723b9aSBill Schmidt } 524fe723b9aSBill Schmidt } 525fe723b9aSBill Schmidt 526fe723b9aSBill Schmidt if (RelevantFunction) { 527d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Swap vector when first built\n\n"); 528d34e60caSNicola Zaghen LLVM_DEBUG(dumpSwapVector()); 529fe723b9aSBill Schmidt } 530fe723b9aSBill Schmidt 531fe723b9aSBill Schmidt return RelevantFunction; 532fe723b9aSBill Schmidt } 533fe723b9aSBill Schmidt 534fe723b9aSBill Schmidt // Add an entry to the swap vector and swap map, and make a 535fe723b9aSBill Schmidt // singleton equivalence class for the entry. 536fe723b9aSBill Schmidt int PPCVSXSwapRemoval::addSwapEntry(MachineInstr *MI, 537fe723b9aSBill Schmidt PPCVSXSwapEntry& SwapEntry) { 538fe723b9aSBill Schmidt SwapEntry.VSEMI = MI; 539fe723b9aSBill Schmidt SwapEntry.VSEId = SwapVector.size(); 540fe723b9aSBill Schmidt SwapVector.push_back(SwapEntry); 541fe723b9aSBill Schmidt EC->insert(SwapEntry.VSEId); 542fe723b9aSBill Schmidt SwapMap[MI] = SwapEntry.VSEId; 543fe723b9aSBill Schmidt return SwapEntry.VSEId; 544fe723b9aSBill Schmidt } 545fe723b9aSBill Schmidt 546fe723b9aSBill Schmidt // This is used to find the "true" source register for an 547fe723b9aSBill Schmidt // XXPERMDI instruction, since MachineCSE does not handle the 548fe723b9aSBill Schmidt // "copy-like" operations (Copy and SubregToReg). Returns 549fe723b9aSBill Schmidt // the original SrcReg unless it is the target of a copy-like 550fe723b9aSBill Schmidt // operation, in which case we chain backwards through all 551fe723b9aSBill Schmidt // such operations to the ultimate source register. If a 552fe723b9aSBill Schmidt // physical register is encountered, we stop the search and 553fe723b9aSBill Schmidt // flag the swap entry indicated by VecIdx (the original 554a1c30053SBill Schmidt // XXPERMDI) as mentioning a physical register. 555fe723b9aSBill Schmidt unsigned PPCVSXSwapRemoval::lookThruCopyLike(unsigned SrcReg, 556fe723b9aSBill Schmidt unsigned VecIdx) { 557fe723b9aSBill Schmidt MachineInstr *MI = MRI->getVRegDef(SrcReg); 558fe723b9aSBill Schmidt if (!MI->isCopyLike()) 559fe723b9aSBill Schmidt return SrcReg; 560fe723b9aSBill Schmidt 561a1c30053SBill Schmidt unsigned CopySrcReg; 562a1c30053SBill Schmidt if (MI->isCopy()) 563fe723b9aSBill Schmidt CopySrcReg = MI->getOperand(1).getReg(); 564a1c30053SBill Schmidt else { 565fe723b9aSBill Schmidt assert(MI->isSubregToReg() && "bad opcode for lookThruCopyLike"); 566fe723b9aSBill Schmidt CopySrcReg = MI->getOperand(2).getReg(); 567fe723b9aSBill Schmidt } 568fe723b9aSBill Schmidt 569fe723b9aSBill Schmidt if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg)) { 5702be8054bSBill Schmidt if (!isScalarVecReg(CopySrcReg)) 571fe723b9aSBill Schmidt SwapVector[VecIdx].MentionsPhysVR = 1; 572fe723b9aSBill Schmidt return CopySrcReg; 573fe723b9aSBill Schmidt } 574fe723b9aSBill Schmidt 575fe723b9aSBill Schmidt return lookThruCopyLike(CopySrcReg, VecIdx); 576fe723b9aSBill Schmidt } 577fe723b9aSBill Schmidt 578fe723b9aSBill Schmidt // Generate equivalence classes for related computations (webs) by 579fe723b9aSBill Schmidt // def-use relationships of virtual registers. Mention of a physical 580fe723b9aSBill Schmidt // register terminates the generation of equivalence classes as this 581fe723b9aSBill Schmidt // indicates a use of a parameter, definition of a return value, use 582fe723b9aSBill Schmidt // of a value returned from a call, or definition of a parameter to a 583fe723b9aSBill Schmidt // call. Computations with physical register mentions are flagged 584fe723b9aSBill Schmidt // as such so their containing webs will not be optimized. 585fe723b9aSBill Schmidt void PPCVSXSwapRemoval::formWebs() { 586fe723b9aSBill Schmidt 587d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n*** Forming webs for swap removal ***\n\n"); 588fe723b9aSBill Schmidt 589fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 590fe723b9aSBill Schmidt 591fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 592fe723b9aSBill Schmidt 593d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n" << SwapVector[EntryIdx].VSEId << " "); 594d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 595fe723b9aSBill Schmidt 596fe723b9aSBill Schmidt // It's sufficient to walk vector uses and join them to their unique 59715deb803SBill Schmidt // definitions. In addition, check full vector register operands 59815deb803SBill Schmidt // for physical regs. We exclude partial-vector register operands 59915deb803SBill Schmidt // because we can handle them if copied to a full vector. 600fe723b9aSBill Schmidt for (const MachineOperand &MO : MI->operands()) { 601fe723b9aSBill Schmidt if (!MO.isReg()) 602fe723b9aSBill Schmidt continue; 603fe723b9aSBill Schmidt 604fe723b9aSBill Schmidt unsigned Reg = MO.getReg(); 60515deb803SBill Schmidt if (!isVecReg(Reg) && !isScalarVecReg(Reg)) 606fe723b9aSBill Schmidt continue; 607fe723b9aSBill Schmidt 608fe723b9aSBill Schmidt if (!TargetRegisterInfo::isVirtualRegister(Reg)) { 60915deb803SBill Schmidt if (!(MI->isCopy() && isScalarVecReg(Reg))) 610fe723b9aSBill Schmidt SwapVector[EntryIdx].MentionsPhysVR = 1; 611fe723b9aSBill Schmidt continue; 612fe723b9aSBill Schmidt } 613fe723b9aSBill Schmidt 614fe723b9aSBill Schmidt if (!MO.isUse()) 615fe723b9aSBill Schmidt continue; 616fe723b9aSBill Schmidt 617fe723b9aSBill Schmidt MachineInstr* DefMI = MRI->getVRegDef(Reg); 618fe723b9aSBill Schmidt assert(SwapMap.find(DefMI) != SwapMap.end() && 619fe723b9aSBill Schmidt "Inconsistency: def of vector reg not found in swap map!"); 620fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 621fe723b9aSBill Schmidt (void)EC->unionSets(SwapVector[DefIdx].VSEId, 622fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId); 623fe723b9aSBill Schmidt 624d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << format("Unioning %d with %d\n", 625d34e60caSNicola Zaghen SwapVector[DefIdx].VSEId, 626fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId)); 627d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Def: "); 628d34e60caSNicola Zaghen LLVM_DEBUG(DefMI->dump()); 629fe723b9aSBill Schmidt } 630fe723b9aSBill Schmidt } 631fe723b9aSBill Schmidt } 632fe723b9aSBill Schmidt 633fe723b9aSBill Schmidt // Walk the swap vector entries looking for conditions that prevent their 634fe723b9aSBill Schmidt // containing computations from being optimized. When such conditions are 635fe723b9aSBill Schmidt // found, mark the representative of the computation's equivalence class 636fe723b9aSBill Schmidt // as rejected. 637fe723b9aSBill Schmidt void PPCVSXSwapRemoval::recordUnoptimizableWebs() { 638fe723b9aSBill Schmidt 639d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n*** Rejecting webs for swap removal ***\n\n"); 640fe723b9aSBill Schmidt 641fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 642fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 643fe723b9aSBill Schmidt 64415deb803SBill Schmidt // If representative is already rejected, don't waste further time. 64515deb803SBill Schmidt if (SwapVector[Repr].WebRejected) 64615deb803SBill Schmidt continue; 64715deb803SBill Schmidt 64815deb803SBill Schmidt // Reject webs containing mentions of physical or partial registers, or 64915deb803SBill Schmidt // containing operations that we don't know how to handle in a lane- 65015deb803SBill Schmidt // permuted region. 651fe723b9aSBill Schmidt if (SwapVector[EntryIdx].MentionsPhysVR || 65215deb803SBill Schmidt SwapVector[EntryIdx].MentionsPartialVR || 653fe723b9aSBill Schmidt !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) { 654fe723b9aSBill Schmidt 655fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 656fe723b9aSBill Schmidt 657d34e60caSNicola Zaghen LLVM_DEBUG( 658d34e60caSNicola Zaghen dbgs() << format("Web %d rejected for physreg, partial reg, or not " 659d34e60caSNicola Zaghen "swap[pable]\n", 660d34e60caSNicola Zaghen Repr)); 661d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " in " << EntryIdx << ": "); 662d34e60caSNicola Zaghen LLVM_DEBUG(SwapVector[EntryIdx].VSEMI->dump()); 663d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n"); 664fe723b9aSBill Schmidt } 665fe723b9aSBill Schmidt 666fe723b9aSBill Schmidt // Reject webs than contain swapping loads that feed something other 667fe723b9aSBill Schmidt // than a swap instruction. 668fe723b9aSBill Schmidt else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { 669fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 670fe723b9aSBill Schmidt unsigned DefReg = MI->getOperand(0).getReg(); 671fe723b9aSBill Schmidt 672fe723b9aSBill Schmidt // We skip debug instructions in the analysis. (Note that debug 673fe723b9aSBill Schmidt // location information is still maintained by this optimization 674fe723b9aSBill Schmidt // because it remains on the LXVD2X and STXVD2X instructions after 675fe723b9aSBill Schmidt // the XXPERMDIs are removed.) 676fe723b9aSBill Schmidt for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { 677fe723b9aSBill Schmidt int UseIdx = SwapMap[&UseMI]; 678fe723b9aSBill Schmidt 679fe723b9aSBill Schmidt if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad || 680fe723b9aSBill Schmidt SwapVector[UseIdx].IsStore) { 681fe723b9aSBill Schmidt 682fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 683fe723b9aSBill Schmidt 684d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << format( 685d34e60caSNicola Zaghen "Web %d rejected for load not feeding swap\n", Repr)); 686d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " def " << EntryIdx << ": "); 687d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 688d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); 689d34e60caSNicola Zaghen LLVM_DEBUG(UseMI.dump()); 690d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n"); 691fe723b9aSBill Schmidt } 692fe723b9aSBill Schmidt } 693fe723b9aSBill Schmidt 69415deb803SBill Schmidt // Reject webs that contain swapping stores that are fed by something 695fe723b9aSBill Schmidt // other than a swap instruction. 696fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { 697fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 698fe723b9aSBill Schmidt unsigned UseReg = MI->getOperand(0).getReg(); 699fe723b9aSBill Schmidt MachineInstr *DefMI = MRI->getVRegDef(UseReg); 700f9d0a405SKit Barton unsigned DefReg = DefMI->getOperand(0).getReg(); 701fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 702fe723b9aSBill Schmidt 703fe723b9aSBill Schmidt if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad || 704fe723b9aSBill Schmidt SwapVector[DefIdx].IsStore) { 705fe723b9aSBill Schmidt 706fe723b9aSBill Schmidt SwapVector[Repr].WebRejected = 1; 707fe723b9aSBill Schmidt 708d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << format( 709d34e60caSNicola Zaghen "Web %d rejected for store not fed by swap\n", Repr)); 710d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " def " << DefIdx << ": "); 711d34e60caSNicola Zaghen LLVM_DEBUG(DefMI->dump()); 712d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " use " << EntryIdx << ": "); 713d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 714d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n"); 715fe723b9aSBill Schmidt } 716f9d0a405SKit Barton 717f9d0a405SKit Barton // Ensure all uses of the register defined by DefMI feed store 718f9d0a405SKit Barton // instructions 719f9d0a405SKit Barton for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { 720f9d0a405SKit Barton int UseIdx = SwapMap[&UseMI]; 721f9d0a405SKit Barton 722f9d0a405SKit Barton if (SwapVector[UseIdx].VSEMI->getOpcode() != MI->getOpcode()) { 723f9d0a405SKit Barton SwapVector[Repr].WebRejected = 1; 724f9d0a405SKit Barton 725d34e60caSNicola Zaghen LLVM_DEBUG( 726d34e60caSNicola Zaghen dbgs() << format( 727d34e60caSNicola Zaghen "Web %d rejected for swap not feeding only stores\n", Repr)); 728d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " def " 729d34e60caSNicola Zaghen << " : "); 730d34e60caSNicola Zaghen LLVM_DEBUG(DefMI->dump()); 731d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " use " << UseIdx << ": "); 732d34e60caSNicola Zaghen LLVM_DEBUG(SwapVector[UseIdx].VSEMI->dump()); 733d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n"); 734f9d0a405SKit Barton } 735f9d0a405SKit Barton } 736fe723b9aSBill Schmidt } 737fe723b9aSBill Schmidt } 738fe723b9aSBill Schmidt 739d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Swap vector after web analysis:\n\n"); 740d34e60caSNicola Zaghen LLVM_DEBUG(dumpSwapVector()); 741fe723b9aSBill Schmidt } 742fe723b9aSBill Schmidt 743fe723b9aSBill Schmidt // Walk the swap vector entries looking for swaps fed by permuting loads 744fe723b9aSBill Schmidt // and swaps that feed permuting stores. If the containing computation 745fe723b9aSBill Schmidt // has not been marked rejected, mark each such swap for removal. 746fe723b9aSBill Schmidt // (Removal is delayed in case optimization has disturbed the pattern, 747fe723b9aSBill Schmidt // such that multiple loads feed the same swap, etc.) 748fe723b9aSBill Schmidt void PPCVSXSwapRemoval::markSwapsForRemoval() { 749fe723b9aSBill Schmidt 750d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n*** Marking swaps for removal ***\n\n"); 751fe723b9aSBill Schmidt 752fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 753fe723b9aSBill Schmidt 754fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) { 755fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 756fe723b9aSBill Schmidt 757fe723b9aSBill Schmidt if (!SwapVector[Repr].WebRejected) { 758fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 759fe723b9aSBill Schmidt unsigned DefReg = MI->getOperand(0).getReg(); 760fe723b9aSBill Schmidt 761fe723b9aSBill Schmidt for (MachineInstr &UseMI : MRI->use_nodbg_instructions(DefReg)) { 762fe723b9aSBill Schmidt int UseIdx = SwapMap[&UseMI]; 763fe723b9aSBill Schmidt SwapVector[UseIdx].WillRemove = 1; 764fe723b9aSBill Schmidt 765d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Marking swap fed by load for removal: "); 766d34e60caSNicola Zaghen LLVM_DEBUG(UseMI.dump()); 767fe723b9aSBill Schmidt } 768fe723b9aSBill Schmidt } 769fe723b9aSBill Schmidt 770fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) { 771fe723b9aSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 772fe723b9aSBill Schmidt 773fe723b9aSBill Schmidt if (!SwapVector[Repr].WebRejected) { 774fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 775fe723b9aSBill Schmidt unsigned UseReg = MI->getOperand(0).getReg(); 776fe723b9aSBill Schmidt MachineInstr *DefMI = MRI->getVRegDef(UseReg); 777fe723b9aSBill Schmidt int DefIdx = SwapMap[DefMI]; 778fe723b9aSBill Schmidt SwapVector[DefIdx].WillRemove = 1; 779fe723b9aSBill Schmidt 780d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Marking swap feeding store for removal: "); 781d34e60caSNicola Zaghen LLVM_DEBUG(DefMI->dump()); 782fe723b9aSBill Schmidt } 783fe723b9aSBill Schmidt 784fe723b9aSBill Schmidt } else if (SwapVector[EntryIdx].IsSwappable && 7855fe2e25fSBill Schmidt SwapVector[EntryIdx].SpecialHandling != 0) { 7865fe2e25fSBill Schmidt int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId); 7875fe2e25fSBill Schmidt 7885fe2e25fSBill Schmidt if (!SwapVector[Repr].WebRejected) 789fe723b9aSBill Schmidt handleSpecialSwappables(EntryIdx); 790fe723b9aSBill Schmidt } 791fe723b9aSBill Schmidt } 7925fe2e25fSBill Schmidt } 793fe723b9aSBill Schmidt 7942be8054bSBill Schmidt // Create an xxswapd instruction and insert it prior to the given point. 7952be8054bSBill Schmidt // MI is used to determine basic block and debug loc information. 7962be8054bSBill Schmidt // FIXME: When inserting a swap, we should check whether SrcReg is 7972be8054bSBill Schmidt // defined by another swap: SrcReg = XXPERMDI Reg, Reg, 2; If so, 7982be8054bSBill Schmidt // then instead we should generate a copy from Reg to DstReg. 7992be8054bSBill Schmidt void PPCVSXSwapRemoval::insertSwap(MachineInstr *MI, 8002be8054bSBill Schmidt MachineBasicBlock::iterator InsertPoint, 8012be8054bSBill Schmidt unsigned DstReg, unsigned SrcReg) { 8022be8054bSBill Schmidt BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), 8032be8054bSBill Schmidt TII->get(PPC::XXPERMDI), DstReg) 8042be8054bSBill Schmidt .addReg(SrcReg) 8052be8054bSBill Schmidt .addReg(SrcReg) 8062be8054bSBill Schmidt .addImm(2); 8072be8054bSBill Schmidt } 8082be8054bSBill Schmidt 809fe723b9aSBill Schmidt // The identified swap entry requires special handling to allow its 810fe723b9aSBill Schmidt // containing computation to be optimized. Perform that handling 811fe723b9aSBill Schmidt // here. 81215deb803SBill Schmidt // FIXME: Additional opportunities will be phased in with subsequent 81315deb803SBill Schmidt // patches. 814fe723b9aSBill Schmidt void PPCVSXSwapRemoval::handleSpecialSwappables(int EntryIdx) { 8155fe2e25fSBill Schmidt switch (SwapVector[EntryIdx].SpecialHandling) { 8165fe2e25fSBill Schmidt 8175fe2e25fSBill Schmidt default: 8188ceb323bSBenjamin Kramer llvm_unreachable("Unexpected special handling type"); 8195fe2e25fSBill Schmidt 8205fe2e25fSBill Schmidt // For splats based on an index into a vector, add N/2 modulo N 8215fe2e25fSBill Schmidt // to the index, where N is the number of vector elements. 8225fe2e25fSBill Schmidt case SHValues::SH_SPLAT: { 8235fe2e25fSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 8245fe2e25fSBill Schmidt unsigned NElts; 8255fe2e25fSBill Schmidt 826d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Changing splat: "); 827d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 8285fe2e25fSBill Schmidt 8295fe2e25fSBill Schmidt switch (MI->getOpcode()) { 8305fe2e25fSBill Schmidt default: 8318ceb323bSBenjamin Kramer llvm_unreachable("Unexpected splat opcode"); 8325fe2e25fSBill Schmidt case PPC::VSPLTB: NElts = 16; break; 8335fe2e25fSBill Schmidt case PPC::VSPLTH: NElts = 8; break; 8341a2b2f03SNemanja Ivanovic case PPC::VSPLTW: 8351a2b2f03SNemanja Ivanovic case PPC::XXSPLTW: NElts = 4; break; 8365fe2e25fSBill Schmidt } 8375fe2e25fSBill Schmidt 8381a2b2f03SNemanja Ivanovic unsigned EltNo; 8391a2b2f03SNemanja Ivanovic if (MI->getOpcode() == PPC::XXSPLTW) 8401a2b2f03SNemanja Ivanovic EltNo = MI->getOperand(2).getImm(); 8411a2b2f03SNemanja Ivanovic else 8421a2b2f03SNemanja Ivanovic EltNo = MI->getOperand(1).getImm(); 8431a2b2f03SNemanja Ivanovic 8445fe2e25fSBill Schmidt EltNo = (EltNo + NElts / 2) % NElts; 8451a2b2f03SNemanja Ivanovic if (MI->getOpcode() == PPC::XXSPLTW) 8461a2b2f03SNemanja Ivanovic MI->getOperand(2).setImm(EltNo); 8471a2b2f03SNemanja Ivanovic else 8485fe2e25fSBill Schmidt MI->getOperand(1).setImm(EltNo); 8495fe2e25fSBill Schmidt 850d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Into: "); 851d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 8525fe2e25fSBill Schmidt break; 8535fe2e25fSBill Schmidt } 8545fe2e25fSBill Schmidt 85515deb803SBill Schmidt // For an XXPERMDI that isn't handled otherwise, we need to 85615deb803SBill Schmidt // reverse the order of the operands. If the selector operand 85715deb803SBill Schmidt // has a value of 0 or 3, we need to change it to 3 or 0, 85815deb803SBill Schmidt // respectively. Otherwise we should leave it alone. (This 85915deb803SBill Schmidt // is equivalent to reversing the two bits of the selector 86015deb803SBill Schmidt // operand and complementing the result.) 86115deb803SBill Schmidt case SHValues::SH_XXPERMDI: { 86215deb803SBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 86315deb803SBill Schmidt 864d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Changing XXPERMDI: "); 865d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 86615deb803SBill Schmidt 86715deb803SBill Schmidt unsigned Selector = MI->getOperand(3).getImm(); 86815deb803SBill Schmidt if (Selector == 0 || Selector == 3) 86915deb803SBill Schmidt Selector = 3 - Selector; 87015deb803SBill Schmidt MI->getOperand(3).setImm(Selector); 87115deb803SBill Schmidt 87215deb803SBill Schmidt unsigned Reg1 = MI->getOperand(1).getReg(); 87315deb803SBill Schmidt unsigned Reg2 = MI->getOperand(2).getReg(); 87415deb803SBill Schmidt MI->getOperand(1).setReg(Reg2); 87515deb803SBill Schmidt MI->getOperand(2).setReg(Reg1); 87615deb803SBill Schmidt 8779bffc94cSHiroshi Inoue // We also need to swap kill flag associated with the register. 8789bffc94cSHiroshi Inoue bool IsKill1 = MI->getOperand(1).isKill(); 8799bffc94cSHiroshi Inoue bool IsKill2 = MI->getOperand(2).isKill(); 8809bffc94cSHiroshi Inoue MI->getOperand(1).setIsKill(IsKill2); 8819bffc94cSHiroshi Inoue MI->getOperand(2).setIsKill(IsKill1); 8829bffc94cSHiroshi Inoue 883d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Into: "); 884d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 88515deb803SBill Schmidt break; 88615deb803SBill Schmidt } 88715deb803SBill Schmidt 88815deb803SBill Schmidt // For a copy from a scalar floating-point register to a vector 88915deb803SBill Schmidt // register, removing swaps will leave the copied value in the 89015deb803SBill Schmidt // wrong lane. Insert a swap following the copy to fix this. 8912be8054bSBill Schmidt case SHValues::SH_COPYWIDEN: { 89215deb803SBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 89315deb803SBill Schmidt 894d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Changing SUBREG_TO_REG: "); 895d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 89615deb803SBill Schmidt 89715deb803SBill Schmidt unsigned DstReg = MI->getOperand(0).getReg(); 89815deb803SBill Schmidt const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg); 89915deb803SBill Schmidt unsigned NewVReg = MRI->createVirtualRegister(DstRC); 90015deb803SBill Schmidt 90115deb803SBill Schmidt MI->getOperand(0).setReg(NewVReg); 902d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << " Into: "); 903d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 90415deb803SBill Schmidt 905a3da4488SDuncan P. N. Exon Smith auto InsertPoint = ++MachineBasicBlock::iterator(MI); 90615deb803SBill Schmidt 90715deb803SBill Schmidt // Note that an XXPERMDI requires a VSRC, so if the SUBREG_TO_REG 90815deb803SBill Schmidt // is copying to a VRRC, we need to be careful to avoid a register 90915deb803SBill Schmidt // assignment problem. In this case we must copy from VRRC to VSRC 91015deb803SBill Schmidt // prior to the swap, and from VSRC to VRRC following the swap. 91115deb803SBill Schmidt // Coalescing will usually remove all this mess. 91215deb803SBill Schmidt if (DstRC == &PPC::VRRCRegClass) { 91315deb803SBill Schmidt unsigned VSRCTmp1 = MRI->createVirtualRegister(&PPC::VSRCRegClass); 91415deb803SBill Schmidt unsigned VSRCTmp2 = MRI->createVirtualRegister(&PPC::VSRCRegClass); 91515deb803SBill Schmidt 91615deb803SBill Schmidt BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), 91715deb803SBill Schmidt TII->get(PPC::COPY), VSRCTmp1) 91815deb803SBill Schmidt .addReg(NewVReg); 919d34e60caSNicola Zaghen LLVM_DEBUG(std::prev(InsertPoint)->dump()); 92015deb803SBill Schmidt 9212be8054bSBill Schmidt insertSwap(MI, InsertPoint, VSRCTmp2, VSRCTmp1); 922d34e60caSNicola Zaghen LLVM_DEBUG(std::prev(InsertPoint)->dump()); 92315deb803SBill Schmidt 92415deb803SBill Schmidt BuildMI(*MI->getParent(), InsertPoint, MI->getDebugLoc(), 92515deb803SBill Schmidt TII->get(PPC::COPY), DstReg) 92615deb803SBill Schmidt .addReg(VSRCTmp2); 927d34e60caSNicola Zaghen LLVM_DEBUG(std::prev(InsertPoint)->dump()); 92815deb803SBill Schmidt 92915deb803SBill Schmidt } else { 9302be8054bSBill Schmidt insertSwap(MI, InsertPoint, DstReg, NewVReg); 931d34e60caSNicola Zaghen LLVM_DEBUG(std::prev(InsertPoint)->dump()); 93215deb803SBill Schmidt } 93315deb803SBill Schmidt break; 93415deb803SBill Schmidt } 9355fe2e25fSBill Schmidt } 936fe723b9aSBill Schmidt } 937fe723b9aSBill Schmidt 938fe723b9aSBill Schmidt // Walk the swap vector and replace each entry marked for removal with 939fe723b9aSBill Schmidt // a copy operation. 940fe723b9aSBill Schmidt bool PPCVSXSwapRemoval::removeSwaps() { 941fe723b9aSBill Schmidt 942d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\n*** Removing swaps ***\n\n"); 943fe723b9aSBill Schmidt 944fe723b9aSBill Schmidt bool Changed = false; 945fe723b9aSBill Schmidt 946fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 947fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WillRemove) { 948fe723b9aSBill Schmidt Changed = true; 949fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 950fe723b9aSBill Schmidt MachineBasicBlock *MBB = MI->getParent(); 951116bbab4SDiana Picus BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(TargetOpcode::COPY), 952116bbab4SDiana Picus MI->getOperand(0).getReg()) 953116bbab4SDiana Picus .add(MI->getOperand(1)); 954fe723b9aSBill Schmidt 955d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << format("Replaced %d with copy: ", 956fe723b9aSBill Schmidt SwapVector[EntryIdx].VSEId)); 957d34e60caSNicola Zaghen LLVM_DEBUG(MI->dump()); 958fe723b9aSBill Schmidt 959fe723b9aSBill Schmidt MI->eraseFromParent(); 960fe723b9aSBill Schmidt } 961fe723b9aSBill Schmidt } 962fe723b9aSBill Schmidt 963fe723b9aSBill Schmidt return Changed; 964fe723b9aSBill Schmidt } 965fe723b9aSBill Schmidt 966615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 967fe723b9aSBill Schmidt // For debug purposes, dump the contents of the swap vector. 9688c209aa8SMatthias Braun LLVM_DUMP_METHOD void PPCVSXSwapRemoval::dumpSwapVector() { 969fe723b9aSBill Schmidt 970fe723b9aSBill Schmidt for (unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) { 971fe723b9aSBill Schmidt 972fe723b9aSBill Schmidt MachineInstr *MI = SwapVector[EntryIdx].VSEMI; 973fe723b9aSBill Schmidt int ID = SwapVector[EntryIdx].VSEId; 974fe723b9aSBill Schmidt 9758c209aa8SMatthias Braun dbgs() << format("%6d", ID); 9768c209aa8SMatthias Braun dbgs() << format("%6d", EC->getLeaderValue(ID)); 97725528d6dSFrancis Visoiu Mistrih dbgs() << format(" %bb.%3d", MI->getParent()->getNumber()); 9788c209aa8SMatthias Braun dbgs() << format(" %14s ", TII->getName(MI->getOpcode()).str().c_str()); 979fe723b9aSBill Schmidt 980fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsLoad) 9818c209aa8SMatthias Braun dbgs() << "load "; 982fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsStore) 9838c209aa8SMatthias Braun dbgs() << "store "; 984fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsSwap) 9858c209aa8SMatthias Braun dbgs() << "swap "; 986fe723b9aSBill Schmidt if (SwapVector[EntryIdx].MentionsPhysVR) 9878c209aa8SMatthias Braun dbgs() << "physreg "; 98815deb803SBill Schmidt if (SwapVector[EntryIdx].MentionsPartialVR) 9898c209aa8SMatthias Braun dbgs() << "partialreg "; 990fe723b9aSBill Schmidt 991fe723b9aSBill Schmidt if (SwapVector[EntryIdx].IsSwappable) { 9928c209aa8SMatthias Braun dbgs() << "swappable "; 993fe723b9aSBill Schmidt switch(SwapVector[EntryIdx].SpecialHandling) { 994fe723b9aSBill Schmidt default: 9958c209aa8SMatthias Braun dbgs() << "special:**unknown**"; 996fe723b9aSBill Schmidt break; 997fe723b9aSBill Schmidt case SH_NONE: 998fe723b9aSBill Schmidt break; 999fe723b9aSBill Schmidt case SH_EXTRACT: 10008c209aa8SMatthias Braun dbgs() << "special:extract "; 1001fe723b9aSBill Schmidt break; 1002fe723b9aSBill Schmidt case SH_INSERT: 10038c209aa8SMatthias Braun dbgs() << "special:insert "; 1004fe723b9aSBill Schmidt break; 1005fe723b9aSBill Schmidt case SH_NOSWAP_LD: 10068c209aa8SMatthias Braun dbgs() << "special:load "; 1007fe723b9aSBill Schmidt break; 1008fe723b9aSBill Schmidt case SH_NOSWAP_ST: 10098c209aa8SMatthias Braun dbgs() << "special:store "; 1010fe723b9aSBill Schmidt break; 1011fe723b9aSBill Schmidt case SH_SPLAT: 10128c209aa8SMatthias Braun dbgs() << "special:splat "; 1013fe723b9aSBill Schmidt break; 101415deb803SBill Schmidt case SH_XXPERMDI: 10158c209aa8SMatthias Braun dbgs() << "special:xxpermdi "; 101615deb803SBill Schmidt break; 10172be8054bSBill Schmidt case SH_COPYWIDEN: 10188c209aa8SMatthias Braun dbgs() << "special:copywiden "; 101915deb803SBill Schmidt break; 1020fe723b9aSBill Schmidt } 1021fe723b9aSBill Schmidt } 1022fe723b9aSBill Schmidt 1023fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WebRejected) 10248c209aa8SMatthias Braun dbgs() << "rejected "; 1025fe723b9aSBill Schmidt if (SwapVector[EntryIdx].WillRemove) 10268c209aa8SMatthias Braun dbgs() << "remove "; 1027fe723b9aSBill Schmidt 10288c209aa8SMatthias Braun dbgs() << "\n"; 1029e71db85bSBill Schmidt 1030e71db85bSBill Schmidt // For no-asserts builds. 1031e71db85bSBill Schmidt (void)MI; 1032e71db85bSBill Schmidt (void)ID; 1033fe723b9aSBill Schmidt } 1034fe723b9aSBill Schmidt 10358c209aa8SMatthias Braun dbgs() << "\n"; 1036fe723b9aSBill Schmidt } 10378c209aa8SMatthias Braun #endif 1038fe723b9aSBill Schmidt 1039f00654e3SAlexander Kornienko } // end default namespace 1040fe723b9aSBill Schmidt 1041fe723b9aSBill Schmidt INITIALIZE_PASS_BEGIN(PPCVSXSwapRemoval, DEBUG_TYPE, 1042fe723b9aSBill Schmidt "PowerPC VSX Swap Removal", false, false) 1043fe723b9aSBill Schmidt INITIALIZE_PASS_END(PPCVSXSwapRemoval, DEBUG_TYPE, 1044fe723b9aSBill Schmidt "PowerPC VSX Swap Removal", false, false) 1045fe723b9aSBill Schmidt 1046fe723b9aSBill Schmidt char PPCVSXSwapRemoval::ID = 0; 1047fe723b9aSBill Schmidt FunctionPass* 1048fe723b9aSBill Schmidt llvm::createPPCVSXSwapRemovalPass() { return new PPCVSXSwapRemoval(); } 1049