181ad6265SDimitry Andric //===-- X86FastPreTileConfig.cpp - Fast Tile Register Configure------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric /// \file Pass to preconfig the shape of physical tile registers 1081ad6265SDimitry Andric /// It inserts ldtilecfg ahead of each group of tile registers. The algorithm 1181ad6265SDimitry Andric /// walk each instruction of basic block in reverse order. All the tile 1281ad6265SDimitry Andric /// registers that live out the basic block would be spilled and reloaded 1381ad6265SDimitry Andric /// before its user. It also check the depenedency of the shape to ensure 1481ad6265SDimitry Andric /// the shape is defined before ldtilecfg. 1581ad6265SDimitry Andric // 1681ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric #include "X86.h" 1981ad6265SDimitry Andric #include "X86InstrBuilder.h" 2081ad6265SDimitry Andric #include "X86MachineFunctionInfo.h" 2181ad6265SDimitry Andric #include "X86RegisterInfo.h" 2281ad6265SDimitry Andric #include "X86Subtarget.h" 2381ad6265SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h" 2481ad6265SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 2581ad6265SDimitry Andric #include "llvm/ADT/Statistic.h" 2681ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 2781ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 2881ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 2981ad6265SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 3081ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h" 3181ad6265SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 3281ad6265SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 3381ad6265SDimitry Andric #include "llvm/InitializePasses.h" 3481ad6265SDimitry Andric #include "llvm/Support/Debug.h" 3581ad6265SDimitry Andric 3681ad6265SDimitry Andric using namespace llvm; 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric #define DEBUG_TYPE "fastpretileconfig" 3981ad6265SDimitry Andric 4081ad6265SDimitry Andric STATISTIC(NumStores, "Number of stores added"); 4181ad6265SDimitry Andric STATISTIC(NumLoads, "Number of loads added"); 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric namespace { 4481ad6265SDimitry Andric 4581ad6265SDimitry Andric class X86FastPreTileConfig : public MachineFunctionPass { 4681ad6265SDimitry Andric MachineFunction *MF = nullptr; 4781ad6265SDimitry Andric const X86Subtarget *ST = nullptr; 4881ad6265SDimitry Andric const TargetInstrInfo *TII = nullptr; 4981ad6265SDimitry Andric MachineRegisterInfo *MRI = nullptr; 5081ad6265SDimitry Andric X86MachineFunctionInfo *X86FI = nullptr; 5181ad6265SDimitry Andric MachineFrameInfo *MFI = nullptr; 5281ad6265SDimitry Andric const TargetRegisterInfo *TRI = nullptr; 5381ad6265SDimitry Andric MachineBasicBlock *MBB = nullptr; 5481ad6265SDimitry Andric int CfgSS = -1; 5581ad6265SDimitry Andric struct PHIInfo { 5681ad6265SDimitry Andric Register Row; 5781ad6265SDimitry Andric Register Col; 5881ad6265SDimitry Andric Register StackAddr; 5981ad6265SDimitry Andric }; 6081ad6265SDimitry Andric DenseMap<MachineInstr *, struct PHIInfo> VisitedPHIs; 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric /// Maps virtual regs to the frame index where these values are spilled. 6381ad6265SDimitry Andric IndexedMap<int, VirtReg2IndexFunctor> StackSlotForVirtReg; 6481ad6265SDimitry Andric 6581ad6265SDimitry Andric /// Has a bit set for tile virtual register for which it was determined 6681ad6265SDimitry Andric /// that it is alive across blocks. 6781ad6265SDimitry Andric BitVector MayLiveAcrossBlocks; 6881ad6265SDimitry Andric 6981ad6265SDimitry Andric int getStackSpaceFor(Register VirtReg); 7081ad6265SDimitry Andric void InitializeTileConfigStackSpace(); 7181ad6265SDimitry Andric bool mayLiveOut(Register VirtReg, MachineInstr *CfgMI); 7281ad6265SDimitry Andric void spill(MachineBasicBlock::iterator Before, Register VirtReg, bool Kill); 7381ad6265SDimitry Andric void reload(MachineBasicBlock::iterator UseMI, Register VirtReg, 7481ad6265SDimitry Andric MachineOperand *RowMO, MachineOperand *ColMO); 7581ad6265SDimitry Andric void canonicalizePHIs(MachineBasicBlock &MBB); 7681ad6265SDimitry Andric void convertPHI(MachineBasicBlock *MBB, MachineInstr &PHI); 7781ad6265SDimitry Andric void convertPHIs(MachineBasicBlock &MBB); 7881ad6265SDimitry Andric bool configBasicBlock(MachineBasicBlock &MBB); 7981ad6265SDimitry Andric 8081ad6265SDimitry Andric public: 8181ad6265SDimitry Andric X86FastPreTileConfig() : MachineFunctionPass(ID), StackSlotForVirtReg(-1) {} 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric /// Return the pass name. 8481ad6265SDimitry Andric StringRef getPassName() const override { 8581ad6265SDimitry Andric return "Fast Tile Register Preconfigure"; 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric /// Perform tile register configure. 8981ad6265SDimitry Andric bool runOnMachineFunction(MachineFunction &MFunc) override; 9081ad6265SDimitry Andric 9181ad6265SDimitry Andric static char ID; 9281ad6265SDimitry Andric }; 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric } // end anonymous namespace 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric char X86FastPreTileConfig::ID = 0; 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric INITIALIZE_PASS_BEGIN(X86FastPreTileConfig, DEBUG_TYPE, 9981ad6265SDimitry Andric "Fast Tile Register Preconfigure", false, false) 10081ad6265SDimitry Andric INITIALIZE_PASS_END(X86FastPreTileConfig, DEBUG_TYPE, 10181ad6265SDimitry Andric "Fast Tile Register Preconfigure", false, false) 10281ad6265SDimitry Andric 10381ad6265SDimitry Andric static bool dominates(MachineBasicBlock &MBB, 10481ad6265SDimitry Andric MachineBasicBlock::const_iterator A, 10581ad6265SDimitry Andric MachineBasicBlock::const_iterator B) { 10681ad6265SDimitry Andric auto MBBEnd = MBB.end(); 10781ad6265SDimitry Andric if (B == MBBEnd) 10881ad6265SDimitry Andric return true; 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric MachineBasicBlock::const_iterator I = MBB.begin(); 11181ad6265SDimitry Andric for (; &*I != A && &*I != B; ++I) 11281ad6265SDimitry Andric ; 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric return &*I == A; 11581ad6265SDimitry Andric } 11681ad6265SDimitry Andric 11781ad6265SDimitry Andric /// This allocates space for the specified virtual register to be held on the 11881ad6265SDimitry Andric /// stack. 11981ad6265SDimitry Andric int X86FastPreTileConfig::getStackSpaceFor(Register VirtReg) { 12081ad6265SDimitry Andric // Find the location Reg would belong... 12181ad6265SDimitry Andric int SS = StackSlotForVirtReg[VirtReg]; 12281ad6265SDimitry Andric // Already has space allocated? 12381ad6265SDimitry Andric if (SS != -1) 12481ad6265SDimitry Andric return SS; 12581ad6265SDimitry Andric 12681ad6265SDimitry Andric // Allocate a new stack object for this spill location... 12781ad6265SDimitry Andric const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg); 12881ad6265SDimitry Andric unsigned Size = TRI->getSpillSize(RC); 12981ad6265SDimitry Andric Align Alignment = TRI->getSpillAlign(RC); 13081ad6265SDimitry Andric int FrameIdx = MFI->CreateSpillStackObject(Size, Alignment); 13181ad6265SDimitry Andric 13281ad6265SDimitry Andric // Assign the slot. 13381ad6265SDimitry Andric StackSlotForVirtReg[VirtReg] = FrameIdx; 13481ad6265SDimitry Andric return FrameIdx; 13581ad6265SDimitry Andric } 13681ad6265SDimitry Andric 13781ad6265SDimitry Andric /// Returns false if \p VirtReg is known to not live out of the current config. 13881ad6265SDimitry Andric /// If \p VirtReg live out of the current MBB, it must live out of the current 13981ad6265SDimitry Andric /// config 14081ad6265SDimitry Andric bool X86FastPreTileConfig::mayLiveOut(Register VirtReg, MachineInstr *CfgMI) { 14181ad6265SDimitry Andric if (MayLiveAcrossBlocks.test(Register::virtReg2Index(VirtReg))) 14281ad6265SDimitry Andric return true; 14381ad6265SDimitry Andric 14481ad6265SDimitry Andric for (const MachineInstr &UseInst : MRI->use_nodbg_instructions(VirtReg)) { 14581ad6265SDimitry Andric if (UseInst.getParent() != MBB) { 14681ad6265SDimitry Andric MayLiveAcrossBlocks.set(Register::virtReg2Index(VirtReg)); 14781ad6265SDimitry Andric return true; 14881ad6265SDimitry Andric } 14981ad6265SDimitry Andric 15081ad6265SDimitry Andric // The use and def are in the same MBB. If the tile register is 15181ad6265SDimitry Andric // reconfigured, it is crobbered and we need to spill and reload 15281ad6265SDimitry Andric // tile register. 15381ad6265SDimitry Andric if (CfgMI) { 15481ad6265SDimitry Andric if (dominates(*MBB, *CfgMI, UseInst)) { 15581ad6265SDimitry Andric MayLiveAcrossBlocks.set(Register::virtReg2Index(VirtReg)); 15681ad6265SDimitry Andric return true; 15781ad6265SDimitry Andric } 15881ad6265SDimitry Andric } 15981ad6265SDimitry Andric } 16081ad6265SDimitry Andric 16181ad6265SDimitry Andric return false; 16281ad6265SDimitry Andric } 16381ad6265SDimitry Andric 16481ad6265SDimitry Andric void X86FastPreTileConfig::InitializeTileConfigStackSpace() { 16581ad6265SDimitry Andric MachineBasicBlock &MBB = MF->front(); 16681ad6265SDimitry Andric MachineInstr *MI = &*MBB.getFirstNonPHI(); 16781ad6265SDimitry Andric DebugLoc DL; 16881ad6265SDimitry Andric if (ST->hasAVX512()) { 16981ad6265SDimitry Andric Register Zmm = MRI->createVirtualRegister(&X86::VR512RegClass); 17081ad6265SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::AVX512_512_SET0), Zmm); 17181ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::VMOVUPSZmr)), CfgSS) 17281ad6265SDimitry Andric .addReg(Zmm); 17381ad6265SDimitry Andric } else if (ST->hasAVX2()) { 17481ad6265SDimitry Andric Register Ymm = MRI->createVirtualRegister(&X86::VR256RegClass); 17581ad6265SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::AVX_SET0), Ymm); 17681ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::VMOVUPSYmr)), CfgSS) 17781ad6265SDimitry Andric .addReg(Ymm); 17881ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::VMOVUPSYmr)), CfgSS, 17981ad6265SDimitry Andric 32) 18081ad6265SDimitry Andric .addReg(Ymm); 18181ad6265SDimitry Andric } else { 18281ad6265SDimitry Andric assert(ST->hasSSE2() && "AMX should assume SSE2 enabled"); 18381ad6265SDimitry Andric unsigned StoreOpc = ST->hasAVX() ? X86::VMOVUPSmr : X86::MOVUPSmr; 18481ad6265SDimitry Andric Register Xmm = MRI->createVirtualRegister(&X86::VR128RegClass); 18581ad6265SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::V_SET0), Xmm); 18681ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(StoreOpc)), CfgSS) 18781ad6265SDimitry Andric .addReg(Xmm); 18881ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(StoreOpc)), CfgSS, 16) 18981ad6265SDimitry Andric .addReg(Xmm); 19081ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(StoreOpc)), CfgSS, 32) 19181ad6265SDimitry Andric .addReg(Xmm); 19281ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(StoreOpc)), CfgSS, 48) 19381ad6265SDimitry Andric .addReg(Xmm); 19481ad6265SDimitry Andric } 19581ad6265SDimitry Andric // Fill in the palette first. 19681ad6265SDimitry Andric addFrameReference(BuildMI(MBB, MI, DL, TII->get(X86::MOV8mi)), CfgSS) 19781ad6265SDimitry Andric .addImm(1); 19881ad6265SDimitry Andric } 19981ad6265SDimitry Andric 20081ad6265SDimitry Andric /// Insert spill instruction for \p AssignedReg before \p Before. 20181ad6265SDimitry Andric /// TODO: Update DBG_VALUEs with \p VirtReg operands with the stack slot. 20281ad6265SDimitry Andric void X86FastPreTileConfig::spill(MachineBasicBlock::iterator Before, 20381ad6265SDimitry Andric Register VirtReg, bool Kill) { 20481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Spilling " << printReg(VirtReg, TRI) << " \n"); 20581ad6265SDimitry Andric int FI = getStackSpaceFor(VirtReg); 20681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " to stack slot #" << FI << '\n'); 20781ad6265SDimitry Andric 20881ad6265SDimitry Andric const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg); 20981ad6265SDimitry Andric // Don't need shape information for tile store, becasue it is adjacent to 21081ad6265SDimitry Andric // the tile def instruction. 211*bdd1243dSDimitry Andric TII->storeRegToStackSlot(*MBB, Before, VirtReg, Kill, FI, &RC, TRI, 212*bdd1243dSDimitry Andric Register()); 21381ad6265SDimitry Andric ++NumStores; 21481ad6265SDimitry Andric 21581ad6265SDimitry Andric // TODO: update DBG_VALUEs 21681ad6265SDimitry Andric } 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric /// Insert reload instruction for \p PhysReg before \p Before. 21981ad6265SDimitry Andric void X86FastPreTileConfig::reload(MachineBasicBlock::iterator UseMI, 22081ad6265SDimitry Andric Register OrigReg, MachineOperand *RowMO, 22181ad6265SDimitry Andric MachineOperand *ColMO) { 22281ad6265SDimitry Andric int FI = getStackSpaceFor(OrigReg); 22381ad6265SDimitry Andric const TargetRegisterClass &RC = *MRI->getRegClass(OrigReg); 22481ad6265SDimitry Andric Register TileReg; 22581ad6265SDimitry Andric // Fold copy to tileload 22681ad6265SDimitry Andric // BB1: 22781ad6265SDimitry Andric // spill src to s 22881ad6265SDimitry Andric // 22981ad6265SDimitry Andric // BB2: 23081ad6265SDimitry Andric // t = copy src 23181ad6265SDimitry Andric // --> 23281ad6265SDimitry Andric // t = tileload (s) 23381ad6265SDimitry Andric if (UseMI->isCopy()) 23481ad6265SDimitry Andric TileReg = UseMI->getOperand(0).getReg(); 23581ad6265SDimitry Andric else 23681ad6265SDimitry Andric TileReg = MRI->createVirtualRegister(&RC); 23781ad6265SDimitry Andric // Can't use TII->loadRegFromStackSlot(), because we need the shape 23881ad6265SDimitry Andric // information for reload. 23981ad6265SDimitry Andric // tileloadd (%sp, %idx), %tmm 24081ad6265SDimitry Andric unsigned Opc = X86::PTILELOADDV; 24181ad6265SDimitry Andric Register StrideReg = MRI->createVirtualRegister(&X86::GR64_NOSPRegClass); 24281ad6265SDimitry Andric // FIXME: MBB is not the parent of UseMI. 24381ad6265SDimitry Andric MachineInstr *NewMI = BuildMI(*UseMI->getParent(), UseMI, DebugLoc(), 24481ad6265SDimitry Andric TII->get(X86::MOV64ri), StrideReg) 24581ad6265SDimitry Andric .addImm(64); 24681ad6265SDimitry Andric NewMI = addFrameReference( 24781ad6265SDimitry Andric BuildMI(*UseMI->getParent(), UseMI, DebugLoc(), TII->get(Opc), TileReg) 24881ad6265SDimitry Andric .addReg(RowMO->getReg()) 24981ad6265SDimitry Andric .addReg(ColMO->getReg()), 25081ad6265SDimitry Andric FI); 25181ad6265SDimitry Andric MachineOperand &MO = NewMI->getOperand(5); 25281ad6265SDimitry Andric MO.setReg(StrideReg); 25381ad6265SDimitry Andric MO.setIsKill(true); 25481ad6265SDimitry Andric RowMO->setIsKill(false); 25581ad6265SDimitry Andric ColMO->setIsKill(false); 25681ad6265SDimitry Andric // Erase copy instruction after it is folded. 25781ad6265SDimitry Andric if (UseMI->isCopy()) { 25881ad6265SDimitry Andric UseMI->eraseFromParent(); 25981ad6265SDimitry Andric } else { 26081ad6265SDimitry Andric // Replace the register in the user MI. 26181ad6265SDimitry Andric for (auto &MO : UseMI->operands()) { 26281ad6265SDimitry Andric if (MO.isReg() && MO.getReg() == OrigReg) 26381ad6265SDimitry Andric MO.setReg(TileReg); 26481ad6265SDimitry Andric } 26581ad6265SDimitry Andric } 26681ad6265SDimitry Andric 26781ad6265SDimitry Andric ++NumLoads; 26881ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Reloading " << printReg(OrigReg, TRI) << " into " 26981ad6265SDimitry Andric << printReg(TileReg, TRI) << '\n'); 27081ad6265SDimitry Andric } 27181ad6265SDimitry Andric 27281ad6265SDimitry Andric static bool isTileDef(MachineRegisterInfo *MRI, MachineInstr &MI) { 27381ad6265SDimitry Andric // The instruction must have 3 operands: tile def, row, col. 27481ad6265SDimitry Andric if (MI.isDebugInstr() || MI.getNumOperands() < 3 || !MI.isPseudo()) 27581ad6265SDimitry Andric return false; 27681ad6265SDimitry Andric MachineOperand &MO = MI.getOperand(0); 27781ad6265SDimitry Andric 27881ad6265SDimitry Andric if (MO.isReg()) { 27981ad6265SDimitry Andric Register Reg = MO.getReg(); 28081ad6265SDimitry Andric // FIXME it may be used after Greedy RA and the physical 28181ad6265SDimitry Andric // register is not rewritten yet. 28281ad6265SDimitry Andric if (Reg.isVirtual() && 28381ad6265SDimitry Andric MRI->getRegClass(Reg)->getID() == X86::TILERegClassID) 28481ad6265SDimitry Andric return true; 28581ad6265SDimitry Andric if (Reg >= X86::TMM0 && Reg <= X86::TMM7) 28681ad6265SDimitry Andric return true; 28781ad6265SDimitry Andric } 28881ad6265SDimitry Andric 28981ad6265SDimitry Andric return false; 29081ad6265SDimitry Andric } 29181ad6265SDimitry Andric 29281ad6265SDimitry Andric static ShapeT getShape(MachineRegisterInfo *MRI, Register TileReg) { 29381ad6265SDimitry Andric MachineInstr *MI = MRI->getVRegDef(TileReg); 29481ad6265SDimitry Andric if (isTileDef(MRI, *MI)) { 29581ad6265SDimitry Andric MachineOperand *RowMO = &MI->getOperand(1); 29681ad6265SDimitry Andric MachineOperand *ColMO = &MI->getOperand(2); 29781ad6265SDimitry Andric return ShapeT(RowMO, ColMO, MRI); 29881ad6265SDimitry Andric } else if (MI->isCopy()) { 29981ad6265SDimitry Andric TileReg = MI->getOperand(1).getReg(); 30081ad6265SDimitry Andric return getShape(MRI, TileReg); 30181ad6265SDimitry Andric } 30281ad6265SDimitry Andric 30381ad6265SDimitry Andric // The def should not be PHI node, because we walk the MBB in reverse post 30481ad6265SDimitry Andric // order. 30581ad6265SDimitry Andric assert(MI->isPHI() && "Unexpected PHI when get shape."); 30681ad6265SDimitry Andric llvm_unreachable("Unexpected MI when get shape."); 30781ad6265SDimitry Andric } 30881ad6265SDimitry Andric 30981ad6265SDimitry Andric // BB0: 31081ad6265SDimitry Andric // spill t0 to s0 31181ad6265SDimitry Andric // BB1: 31281ad6265SDimitry Andric // spill t1 to s1 31381ad6265SDimitry Andric // 31481ad6265SDimitry Andric // BB2: 31581ad6265SDimitry Andric // t = phi [t0, bb0] [t1, bb1] 31681ad6265SDimitry Andric // --> 31781ad6265SDimitry Andric // row = phi [r0, bb0] [r1, bb1] 31881ad6265SDimitry Andric // col = phi [c0, bb0] [c1, bb1] 31981ad6265SDimitry Andric // s = phi [s0, bb0] [s1, bb1] 32081ad6265SDimitry Andric // t = tileload row, col, s 32181ad6265SDimitry Andric // The new instruction is inserted at the end of the phi node. The order 32281ad6265SDimitry Andric // of the original phi node is not ensured. 32381ad6265SDimitry Andric void X86FastPreTileConfig::convertPHI(MachineBasicBlock *MBB, 32481ad6265SDimitry Andric MachineInstr &PHI) { 32581ad6265SDimitry Andric // 1. Create instruction to get stack slot address of each incoming block. 32681ad6265SDimitry Andric // 2. Create PHI node for the stack address. 32781ad6265SDimitry Andric // 3. Create PHI node for shape. If one of the incoming shape is immediate 32881ad6265SDimitry Andric // use the immediate and delete the PHI node. 32981ad6265SDimitry Andric // 4. Create tileload instruction from the stack address. 33081ad6265SDimitry Andric Register StackAddrReg = MRI->createVirtualRegister(&X86::GR64_NOSPRegClass); 33181ad6265SDimitry Andric MachineInstrBuilder AddrPHI = BuildMI(*MBB, ++PHI.getIterator(), DebugLoc(), 33281ad6265SDimitry Andric TII->get(X86::PHI), StackAddrReg); 33381ad6265SDimitry Andric Register RowReg = MRI->createVirtualRegister(&X86::GR16RegClass); 33481ad6265SDimitry Andric MachineInstrBuilder RowPHI = BuildMI(*MBB, ++PHI.getIterator(), DebugLoc(), 33581ad6265SDimitry Andric TII->get(X86::PHI), RowReg); 33681ad6265SDimitry Andric Register ColReg = MRI->createVirtualRegister(&X86::GR16RegClass); 33781ad6265SDimitry Andric MachineInstrBuilder ColPHI = BuildMI(*MBB, ++PHI.getIterator(), DebugLoc(), 33881ad6265SDimitry Andric TII->get(X86::PHI), ColReg); 33981ad6265SDimitry Andric // Record the mapping of phi node and its row/column information. 34081ad6265SDimitry Andric VisitedPHIs[&PHI] = {RowReg, ColReg, StackAddrReg}; 34181ad6265SDimitry Andric 34281ad6265SDimitry Andric for (unsigned I = 1, E = PHI.getNumOperands(); I != E; I += 2) { 34381ad6265SDimitry Andric // Get the 2 incoming value of tile register and MBB. 34481ad6265SDimitry Andric Register InTileReg = PHI.getOperand(I).getReg(); 34581ad6265SDimitry Andric // Mark it as liveout, so that it will be spilled when visit 34681ad6265SDimitry Andric // the incoming MBB. Otherwise since phi will be deleted, it 34781ad6265SDimitry Andric // would miss spill when visit incoming MBB. 34881ad6265SDimitry Andric MayLiveAcrossBlocks.set(Register::virtReg2Index(InTileReg)); 34981ad6265SDimitry Andric MachineBasicBlock *InMBB = PHI.getOperand(I + 1).getMBB(); 35081ad6265SDimitry Andric 35181ad6265SDimitry Andric MachineInstr *TileDefMI = MRI->getVRegDef(InTileReg); 35281ad6265SDimitry Andric MachineBasicBlock::iterator InsertPos; 35381ad6265SDimitry Andric if (TileDefMI->isPHI()) { 35481ad6265SDimitry Andric InsertPos = TileDefMI->getParent()->getFirstNonPHI(); 35581ad6265SDimitry Andric if (VisitedPHIs.count(TileDefMI)) { // circular phi reference 35681ad6265SDimitry Andric // def t1 35781ad6265SDimitry Andric // / \ 35881ad6265SDimitry Andric // def t2 t3 = phi(t1, t4) <-- 35981ad6265SDimitry Andric // \ / | 36081ad6265SDimitry Andric // t4 = phi(t2, t3)------------- 36181ad6265SDimitry Andric // 36281ad6265SDimitry Andric // For each (row, column and stack address) append phi incoming value. 36381ad6265SDimitry Andric // Create r3 = phi(r1, r4) 36481ad6265SDimitry Andric // Create r4 = phi(r2, r3) 36581ad6265SDimitry Andric Register InRowReg = VisitedPHIs[TileDefMI].Row; 36681ad6265SDimitry Andric Register InColReg = VisitedPHIs[TileDefMI].Col; 36781ad6265SDimitry Andric Register InStackAddrReg = VisitedPHIs[TileDefMI].StackAddr; 36881ad6265SDimitry Andric RowPHI.addReg(InRowReg).addMBB(InMBB); 36981ad6265SDimitry Andric ColPHI.addReg(InColReg).addMBB(InMBB); 37081ad6265SDimitry Andric AddrPHI.addReg(InStackAddrReg).addMBB(InMBB); 37181ad6265SDimitry Andric continue; 37281ad6265SDimitry Andric } else { 37381ad6265SDimitry Andric // Recursively convert PHI to tileload 37481ad6265SDimitry Andric convertPHI(TileDefMI->getParent(), *TileDefMI); 37581ad6265SDimitry Andric // The PHI node is coverted to tileload instruction. Get the stack 37681ad6265SDimitry Andric // address from tileload operands. 37781ad6265SDimitry Andric MachineInstr *TileLoad = MRI->getVRegDef(InTileReg); 37881ad6265SDimitry Andric assert(TileLoad && TileLoad->getOpcode() == X86::PTILELOADDV); 37981ad6265SDimitry Andric Register InRowReg = TileLoad->getOperand(1).getReg(); 38081ad6265SDimitry Andric Register InColReg = TileLoad->getOperand(2).getReg(); 38181ad6265SDimitry Andric Register InStackAddrReg = TileLoad->getOperand(3).getReg(); 38281ad6265SDimitry Andric RowPHI.addReg(InRowReg).addMBB(InMBB); 38381ad6265SDimitry Andric ColPHI.addReg(InColReg).addMBB(InMBB); 38481ad6265SDimitry Andric AddrPHI.addReg(InStackAddrReg).addMBB(InMBB); 38581ad6265SDimitry Andric } 38681ad6265SDimitry Andric } else { 38781ad6265SDimitry Andric InsertPos = TileDefMI->getIterator(); 38881ad6265SDimitry Andric 38981ad6265SDimitry Andric // Fill the incoming operand of row/column phi instruction. 39081ad6265SDimitry Andric ShapeT Shape = getShape(MRI, InTileReg); 39181ad6265SDimitry Andric Shape.getRow()->setIsKill(false); 39281ad6265SDimitry Andric Shape.getCol()->setIsKill(false); 39381ad6265SDimitry Andric RowPHI.addReg(Shape.getRow()->getReg()).addMBB(InMBB); 39481ad6265SDimitry Andric ColPHI.addReg(Shape.getCol()->getReg()).addMBB(InMBB); 39581ad6265SDimitry Andric 39681ad6265SDimitry Andric // The incoming tile register live out of its def BB, it would be spilled. 39781ad6265SDimitry Andric // Create MI to get the spill stack slot address for the tile register 39881ad6265SDimitry Andric int FI = getStackSpaceFor(InTileReg); 39981ad6265SDimitry Andric Register InStackAddrReg = 40081ad6265SDimitry Andric MRI->createVirtualRegister(&X86::GR64_NOSPRegClass); 40181ad6265SDimitry Andric addOffset(BuildMI(*TileDefMI->getParent(), InsertPos, DebugLoc(), 40281ad6265SDimitry Andric TII->get(X86::LEA64r), InStackAddrReg) 40381ad6265SDimitry Andric .addFrameIndex(FI), 40481ad6265SDimitry Andric 0); 40581ad6265SDimitry Andric AddrPHI.addReg(InStackAddrReg).addMBB(InMBB); 40681ad6265SDimitry Andric } 40781ad6265SDimitry Andric } 40881ad6265SDimitry Andric 40981ad6265SDimitry Andric MachineBasicBlock::iterator InsertPos = MBB->getFirstNonPHI(); 41081ad6265SDimitry Andric Register StrideReg = MRI->createVirtualRegister(&X86::GR64_NOSPRegClass); 41181ad6265SDimitry Andric BuildMI(*MBB, InsertPos, DebugLoc(), TII->get(X86::MOV64ri), StrideReg) 41281ad6265SDimitry Andric .addImm(64); 41381ad6265SDimitry Andric Register TileReg = PHI.getOperand(0).getReg(); 41481ad6265SDimitry Andric MachineInstr *NewMI = addDirectMem( 41581ad6265SDimitry Andric BuildMI(*MBB, InsertPos, DebugLoc(), TII->get(X86::PTILELOADDV), TileReg) 41681ad6265SDimitry Andric .addReg(RowReg) 41781ad6265SDimitry Andric .addReg(ColReg), 41881ad6265SDimitry Andric StackAddrReg); 41981ad6265SDimitry Andric MachineOperand &MO = NewMI->getOperand(5); 42081ad6265SDimitry Andric MO.setReg(StrideReg); 42181ad6265SDimitry Andric MO.setIsKill(true); 42281ad6265SDimitry Andric PHI.eraseFromParent(); 42381ad6265SDimitry Andric VisitedPHIs.erase(&PHI); 42481ad6265SDimitry Andric } 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric static bool isTileRegDef(MachineRegisterInfo *MRI, MachineInstr &MI) { 42781ad6265SDimitry Andric MachineOperand &MO = MI.getOperand(0); 42881ad6265SDimitry Andric if (MO.isReg() && MO.getReg().isVirtual() && 42981ad6265SDimitry Andric MRI->getRegClass(MO.getReg())->getID() == X86::TILERegClassID) 43081ad6265SDimitry Andric return true; 43181ad6265SDimitry Andric return false; 43281ad6265SDimitry Andric } 43381ad6265SDimitry Andric 43481ad6265SDimitry Andric void X86FastPreTileConfig::canonicalizePHIs(MachineBasicBlock &MBB) { 43581ad6265SDimitry Andric SmallVector<MachineInstr *, 8> PHIs; 43681ad6265SDimitry Andric 43781ad6265SDimitry Andric for (MachineInstr &MI : MBB) { 43881ad6265SDimitry Andric if (!MI.isPHI()) 43981ad6265SDimitry Andric break; 44081ad6265SDimitry Andric if (!isTileRegDef(MRI, MI)) 44181ad6265SDimitry Andric continue; 44281ad6265SDimitry Andric PHIs.push_back(&MI); 44381ad6265SDimitry Andric } 44481ad6265SDimitry Andric // Canonicalize the phi node first. One tile phi may depeneds previous 44581ad6265SDimitry Andric // phi node. For below case, we need convert %t4. 44681ad6265SDimitry Andric // 44781ad6265SDimitry Andric // BB0: 44881ad6265SDimitry Andric // %t3 = phi (t1 BB1, t2 BB0) 44981ad6265SDimitry Andric // %t4 = phi (t5 BB1, t3 BB0) 45081ad6265SDimitry Andric // --> 45181ad6265SDimitry Andric // %t3 = phi (t1 BB1, t2 BB0) 45281ad6265SDimitry Andric // %t4 = phi (t5 BB1, t2 BB0) 45381ad6265SDimitry Andric // 45481ad6265SDimitry Andric while (!PHIs.empty()) { 45581ad6265SDimitry Andric MachineInstr *PHI = PHIs.pop_back_val(); 45681ad6265SDimitry Andric 45781ad6265SDimitry Andric // Find the operand that is incoming from the same MBB and the def 45881ad6265SDimitry Andric // is also phi node. 45981ad6265SDimitry Andric MachineOperand *InMO = nullptr; 46081ad6265SDimitry Andric MachineInstr *DefMI = nullptr; 46181ad6265SDimitry Andric for (unsigned I = 1, E = PHI->getNumOperands(); I != E; I += 2) { 46281ad6265SDimitry Andric Register InTileReg = PHI->getOperand(I).getReg(); 46381ad6265SDimitry Andric MachineBasicBlock *InMBB = PHI->getOperand(I + 1).getMBB(); 46481ad6265SDimitry Andric DefMI = MRI->getVRegDef(InTileReg); 46581ad6265SDimitry Andric if (InMBB != &MBB || !DefMI->isPHI()) 46681ad6265SDimitry Andric continue; 46781ad6265SDimitry Andric 46881ad6265SDimitry Andric InMO = &PHI->getOperand(I); 46981ad6265SDimitry Andric break; 47081ad6265SDimitry Andric } 47181ad6265SDimitry Andric // If can't find such operand, do nothing. 47281ad6265SDimitry Andric if (!InMO) 47381ad6265SDimitry Andric continue; 47481ad6265SDimitry Andric 47581ad6265SDimitry Andric // Current phi node depends on previous phi node. Break the 47681ad6265SDimitry Andric // dependency. 47781ad6265SDimitry Andric Register DefTileReg; 47881ad6265SDimitry Andric for (unsigned I = 1, E = DefMI->getNumOperands(); I != E; I += 2) { 47981ad6265SDimitry Andric MachineBasicBlock *InMBB = PHI->getOperand(I + 1).getMBB(); 48081ad6265SDimitry Andric if (InMBB != &MBB) 48181ad6265SDimitry Andric continue; 48281ad6265SDimitry Andric DefTileReg = DefMI->getOperand(I).getReg(); 48381ad6265SDimitry Andric InMO->setReg(DefTileReg); 48481ad6265SDimitry Andric break; 48581ad6265SDimitry Andric } 48681ad6265SDimitry Andric } 48781ad6265SDimitry Andric } 48881ad6265SDimitry Andric 48981ad6265SDimitry Andric void X86FastPreTileConfig::convertPHIs(MachineBasicBlock &MBB) { 49081ad6265SDimitry Andric SmallVector<MachineInstr *, 8> PHIs; 49181ad6265SDimitry Andric for (MachineInstr &MI : MBB) { 49281ad6265SDimitry Andric if (!MI.isPHI()) 49381ad6265SDimitry Andric break; 49481ad6265SDimitry Andric if (!isTileRegDef(MRI, MI)) 49581ad6265SDimitry Andric continue; 49681ad6265SDimitry Andric PHIs.push_back(&MI); 49781ad6265SDimitry Andric } 49881ad6265SDimitry Andric while (!PHIs.empty()) { 49981ad6265SDimitry Andric MachineInstr *MI = PHIs.pop_back_val(); 50081ad6265SDimitry Andric VisitedPHIs.clear(); 50181ad6265SDimitry Andric convertPHI(&MBB, *MI); 50281ad6265SDimitry Andric } 50381ad6265SDimitry Andric } 50481ad6265SDimitry Andric 50581ad6265SDimitry Andric // PreTileConfig should configure the tile registers based on basic 50681ad6265SDimitry Andric // block. 50781ad6265SDimitry Andric bool X86FastPreTileConfig::configBasicBlock(MachineBasicBlock &MBB) { 50881ad6265SDimitry Andric this->MBB = &MBB; 50981ad6265SDimitry Andric bool Change = false; 51081ad6265SDimitry Andric MachineInstr *LastShapeMI = nullptr; 51181ad6265SDimitry Andric MachineInstr *LastTileCfg = nullptr; 51281ad6265SDimitry Andric bool HasUnconfigTile = false; 51381ad6265SDimitry Andric 51481ad6265SDimitry Andric auto Config = [&](MachineInstr &Before) { 51581ad6265SDimitry Andric if (CfgSS == -1) 51681ad6265SDimitry Andric CfgSS = MFI->CreateStackObject(ST->getTileConfigSize(), 51781ad6265SDimitry Andric ST->getTileConfigAlignment(), false); 51881ad6265SDimitry Andric LastTileCfg = addFrameReference( 51981ad6265SDimitry Andric BuildMI(MBB, Before, DebugLoc(), TII->get(X86::PLDTILECFGV)), CfgSS); 52081ad6265SDimitry Andric LastShapeMI = nullptr; 52181ad6265SDimitry Andric Change = true; 52281ad6265SDimitry Andric }; 52381ad6265SDimitry Andric auto HasTileOperand = [](MachineRegisterInfo *MRI, MachineInstr &MI) { 52481ad6265SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 52581ad6265SDimitry Andric if (!MO.isReg()) 52681ad6265SDimitry Andric continue; 52781ad6265SDimitry Andric Register Reg = MO.getReg(); 52881ad6265SDimitry Andric if (Reg.isVirtual() && 52981ad6265SDimitry Andric MRI->getRegClass(Reg)->getID() == X86::TILERegClassID) 53081ad6265SDimitry Andric return true; 53181ad6265SDimitry Andric } 53281ad6265SDimitry Andric return false; 53381ad6265SDimitry Andric }; 53481ad6265SDimitry Andric for (MachineInstr &MI : reverse(MBB)) { 53581ad6265SDimitry Andric // We have transformed phi node before configuring BB. 53681ad6265SDimitry Andric if (MI.isPHI()) 53781ad6265SDimitry Andric break; 53881ad6265SDimitry Andric // Don't collect the shape of used tile, the tile should be defined 53981ad6265SDimitry Andric // before the tile use. Spill and reload would happen if there is only 54081ad6265SDimitry Andric // tile use after ldtilecfg, so the shape can be collected from reload. 54181ad6265SDimitry Andric // Take below code for example. %t would be reloaded before tilestore 54281ad6265SDimitry Andric // call 54381ad6265SDimitry Andric // .... 54481ad6265SDimitry Andric // tilestore %r, %c, %t 54581ad6265SDimitry Andric // --> 54681ad6265SDimitry Andric // call 54781ad6265SDimitry Andric // ldtilecfg 54881ad6265SDimitry Andric // %t = tileload %r, %c 54981ad6265SDimitry Andric // tilestore %r, %c, %t 55081ad6265SDimitry Andric if (HasTileOperand(MRI, MI)) 55181ad6265SDimitry Andric HasUnconfigTile = true; 55281ad6265SDimitry Andric // According to AMX ABI, all the tile registers including config register 55381ad6265SDimitry Andric // are volatile. Caller need to save/restore config register. 55481ad6265SDimitry Andric if (MI.isCall() && HasUnconfigTile) { 55581ad6265SDimitry Andric MachineBasicBlock::iterator I; 55681ad6265SDimitry Andric if (LastShapeMI && dominates(MBB, MI, LastShapeMI)) 55781ad6265SDimitry Andric I = ++LastShapeMI->getIterator(); 55881ad6265SDimitry Andric else 55981ad6265SDimitry Andric I = ++MI.getIterator(); 56081ad6265SDimitry Andric Config(*I); 56181ad6265SDimitry Andric HasUnconfigTile = false; 56281ad6265SDimitry Andric continue; 56381ad6265SDimitry Andric } 56481ad6265SDimitry Andric if (!isTileDef(MRI, MI)) 56581ad6265SDimitry Andric continue; 56681ad6265SDimitry Andric // 56781ad6265SDimitry Andric //--------------------------------------------------------------------- 56881ad6265SDimitry Andric // Don't handle COPY instruction. If the src and dst of the COPY can be 56981ad6265SDimitry Andric // in the same config in below case, we just check the shape of t0. 57081ad6265SDimitry Andric // def row0 57181ad6265SDimitry Andric // def col0 57281ad6265SDimitry Andric // ldtilecfg 57381ad6265SDimitry Andric // t0 = tielzero(row0, col0) 57481ad6265SDimitry Andric // t1 = copy t0 57581ad6265SDimitry Andric // ... 57681ad6265SDimitry Andric // If the src and dst of the COPY can NOT be in the same config in below 57781ad6265SDimitry Andric // case. Reload would be generated befor the copy instruction. 57881ad6265SDimitry Andric // def row0 57981ad6265SDimitry Andric // def col0 58081ad6265SDimitry Andric // t0 = tielzero(row0, col0) 58181ad6265SDimitry Andric // spill t0 58281ad6265SDimitry Andric // ... 58381ad6265SDimitry Andric // def row1 58481ad6265SDimitry Andric // def col1 58581ad6265SDimitry Andric // ldtilecfg 58681ad6265SDimitry Andric // t1 = tilezero(row1, col1) 58781ad6265SDimitry Andric // reload t0 58881ad6265SDimitry Andric // t1 = copy t0 58981ad6265SDimitry Andric //--------------------------------------------------------------------- 59081ad6265SDimitry Andric // 59181ad6265SDimitry Andric // If MI dominate the last shape def instruction, we need insert 59281ad6265SDimitry Andric // ldtilecfg after LastShapeMI now. The config doesn't include 59381ad6265SDimitry Andric // current MI. 59481ad6265SDimitry Andric // def row0 59581ad6265SDimitry Andric // def col0 59681ad6265SDimitry Andric // tilezero(row0, col0) <- MI 59781ad6265SDimitry Andric // def row1 59881ad6265SDimitry Andric // def col1 59981ad6265SDimitry Andric // ldtilecfg <- insert 60081ad6265SDimitry Andric // tilezero(row1, col1) 60181ad6265SDimitry Andric if (LastShapeMI && dominates(MBB, MI, LastShapeMI)) 60281ad6265SDimitry Andric Config(*(++LastShapeMI->getIterator())); 60381ad6265SDimitry Andric MachineOperand *RowMO = &MI.getOperand(1); 60481ad6265SDimitry Andric MachineOperand *ColMO = &MI.getOperand(2); 60581ad6265SDimitry Andric MachineInstr *RowMI = MRI->getVRegDef(RowMO->getReg()); 60681ad6265SDimitry Andric MachineInstr *ColMI = MRI->getVRegDef(ColMO->getReg()); 60781ad6265SDimitry Andric // If the shape is defined in current MBB, check the domination. 60881ad6265SDimitry Andric // FIXME how about loop? 60981ad6265SDimitry Andric if (RowMI->getParent() == &MBB) { 61081ad6265SDimitry Andric if (!LastShapeMI) 61181ad6265SDimitry Andric LastShapeMI = RowMI; 61281ad6265SDimitry Andric else if (dominates(MBB, LastShapeMI, RowMI)) 61381ad6265SDimitry Andric LastShapeMI = RowMI; 61481ad6265SDimitry Andric } 61581ad6265SDimitry Andric if (ColMI->getParent() == &MBB) { 61681ad6265SDimitry Andric if (!LastShapeMI) 61781ad6265SDimitry Andric LastShapeMI = ColMI; 61881ad6265SDimitry Andric else if (dominates(MBB, LastShapeMI, ColMI)) 61981ad6265SDimitry Andric LastShapeMI = ColMI; 62081ad6265SDimitry Andric } 62181ad6265SDimitry Andric // If there is user live out of the tilecfg, spill it and reload in 62281ad6265SDimitry Andric // before the user. 62381ad6265SDimitry Andric Register TileReg = MI.getOperand(0).getReg(); 62481ad6265SDimitry Andric if (mayLiveOut(TileReg, LastTileCfg)) 62581ad6265SDimitry Andric spill(++MI.getIterator(), TileReg, false); 62681ad6265SDimitry Andric for (MachineInstr &UseMI : MRI->use_instructions(TileReg)) { 62781ad6265SDimitry Andric if (UseMI.getParent() == &MBB) { 62881ad6265SDimitry Andric // check user should not across ldtilecfg 62981ad6265SDimitry Andric if (!LastTileCfg || !dominates(MBB, LastTileCfg, UseMI)) 63081ad6265SDimitry Andric continue; 63181ad6265SDimitry Andric // reload befor UseMI 63281ad6265SDimitry Andric reload(UseMI.getIterator(), TileReg, RowMO, ColMO); 63381ad6265SDimitry Andric } else { 63481ad6265SDimitry Andric // Don't reload for phi instruction, we handle phi reload separately. 63581ad6265SDimitry Andric // TODO: merge the reload for the same user MBB. 63681ad6265SDimitry Andric if (!UseMI.isPHI()) 63781ad6265SDimitry Andric reload(UseMI.getIterator(), TileReg, RowMO, ColMO); 63881ad6265SDimitry Andric } 63981ad6265SDimitry Andric } 64081ad6265SDimitry Andric } 64181ad6265SDimitry Andric 64281ad6265SDimitry Andric // Configure tile registers at the head of the MBB 64381ad6265SDimitry Andric if (HasUnconfigTile) { 64481ad6265SDimitry Andric MachineInstr *Before; 64581ad6265SDimitry Andric if (LastShapeMI == nullptr || LastShapeMI->isPHI()) 64681ad6265SDimitry Andric Before = &*MBB.getFirstNonPHI(); 64781ad6265SDimitry Andric else 64881ad6265SDimitry Andric Before = &*(++LastShapeMI->getIterator()); 64981ad6265SDimitry Andric 65081ad6265SDimitry Andric Config(*Before); 65181ad6265SDimitry Andric } 65281ad6265SDimitry Andric 65381ad6265SDimitry Andric return Change; 65481ad6265SDimitry Andric } 65581ad6265SDimitry Andric 65681ad6265SDimitry Andric bool X86FastPreTileConfig::runOnMachineFunction(MachineFunction &MFunc) { 65781ad6265SDimitry Andric MF = &MFunc; 65881ad6265SDimitry Andric MRI = &MFunc.getRegInfo(); 65981ad6265SDimitry Andric ST = &MFunc.getSubtarget<X86Subtarget>(); 66081ad6265SDimitry Andric TII = ST->getInstrInfo(); 66181ad6265SDimitry Andric X86FI = MFunc.getInfo<X86MachineFunctionInfo>(); 66281ad6265SDimitry Andric MFI = &MFunc.getFrameInfo(); 66381ad6265SDimitry Andric TRI = ST->getRegisterInfo(); 66481ad6265SDimitry Andric CfgSS = -1; 66581ad6265SDimitry Andric 66681ad6265SDimitry Andric unsigned NumVirtRegs = MRI->getNumVirtRegs(); 66781ad6265SDimitry Andric // Abandon early if there is no tile register to config. 66881ad6265SDimitry Andric bool HasVirtTileReg = false; 66981ad6265SDimitry Andric for (unsigned I = 0, E = NumVirtRegs; I != E; ++I) { 67081ad6265SDimitry Andric Register VirtReg = Register::index2VirtReg(I); 67181ad6265SDimitry Andric if (MRI->getRegClass(VirtReg)->getID() == X86::TILERegClassID) { 67281ad6265SDimitry Andric HasVirtTileReg = true; 67381ad6265SDimitry Andric break; 67481ad6265SDimitry Andric } 67581ad6265SDimitry Andric } 67681ad6265SDimitry Andric if (!HasVirtTileReg) 67781ad6265SDimitry Andric return false; 67881ad6265SDimitry Andric 67981ad6265SDimitry Andric StackSlotForVirtReg.resize(NumVirtRegs); 68081ad6265SDimitry Andric MayLiveAcrossBlocks.clear(); 68181ad6265SDimitry Andric // We will create register during config. *3 is to make sure 68281ad6265SDimitry Andric // the virtual register number doesn't exceed the size of 68381ad6265SDimitry Andric // the bit vector. 68481ad6265SDimitry Andric MayLiveAcrossBlocks.resize(NumVirtRegs * 3); 68581ad6265SDimitry Andric bool Change = false; 68681ad6265SDimitry Andric assert(MRI->isSSA()); 68781ad6265SDimitry Andric 68881ad6265SDimitry Andric // Canonicalize the phi node first. 68981ad6265SDimitry Andric for (MachineBasicBlock &MBB : MFunc) 69081ad6265SDimitry Andric canonicalizePHIs(MBB); 69181ad6265SDimitry Andric 69281ad6265SDimitry Andric // Loop over all of the basic blocks in reverse post order and insert 69381ad6265SDimitry Andric // ldtilecfg for tile registers. The reserse post order is to facilitate 69481ad6265SDimitry Andric // PHI node convert. 69581ad6265SDimitry Andric ReversePostOrderTraversal<MachineFunction *> RPOT(MF); 69681ad6265SDimitry Andric for (MachineBasicBlock *MBB : RPOT) { 69781ad6265SDimitry Andric convertPHIs(*MBB); 69881ad6265SDimitry Andric Change |= configBasicBlock(*MBB); 69981ad6265SDimitry Andric } 70081ad6265SDimitry Andric 70181ad6265SDimitry Andric if (Change) 70281ad6265SDimitry Andric InitializeTileConfigStackSpace(); 70381ad6265SDimitry Andric 70481ad6265SDimitry Andric StackSlotForVirtReg.clear(); 70581ad6265SDimitry Andric return Change; 70681ad6265SDimitry Andric } 70781ad6265SDimitry Andric 70881ad6265SDimitry Andric FunctionPass *llvm::createX86FastPreTileConfigPass() { 70981ad6265SDimitry Andric return new X86FastPreTileConfig(); 71081ad6265SDimitry Andric } 711