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:
X86FastPreTileConfig()8081ad6265SDimitry Andric X86FastPreTileConfig() : MachineFunctionPass(ID), StackSlotForVirtReg(-1) {}
8181ad6265SDimitry Andric
8281ad6265SDimitry Andric /// Return the pass name.
getPassName() const8381ad6265SDimitry 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
dominates(MachineBasicBlock & MBB,MachineBasicBlock::const_iterator A,MachineBasicBlock::const_iterator B)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.
getStackSpaceFor(Register VirtReg)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
mayLiveOut(Register VirtReg,MachineInstr * CfgMI)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
InitializeTileConfigStackSpace()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.
spill(MachineBasicBlock::iterator Before,Register VirtReg,bool Kill)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.
reload(MachineBasicBlock::iterator UseMI,Register OrigReg,MachineOperand * RowMO,MachineOperand * ColMO)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
isTileDef(MachineRegisterInfo * MRI,MachineInstr & MI)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
getShape(MachineRegisterInfo * MRI,Register TileReg)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.
convertPHI(MachineBasicBlock * MBB,MachineInstr & PHI)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
isTileRegDef(MachineRegisterInfo * MRI,MachineInstr & MI)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
canonicalizePHIs(MachineBasicBlock & MBB)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
convertPHIs(MachineBasicBlock & MBB)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.
configBasicBlock(MachineBasicBlock & MBB)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
runOnMachineFunction(MachineFunction & MFunc)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
createX86FastPreTileConfigPass()70081ad6265SDimitry Andric FunctionPass *llvm::createX86FastPreTileConfigPass() {
70181ad6265SDimitry Andric return new X86FastPreTileConfig();
70281ad6265SDimitry Andric }
703