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