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