18bcb0991SDimitry Andric //===-- MVEVPTBlockPass.cpp - Insert MVE VPT blocks -----------------------===// 28bcb0991SDimitry Andric // 38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bcb0991SDimitry Andric // 78bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 88bcb0991SDimitry Andric 98bcb0991SDimitry Andric #include "ARM.h" 108bcb0991SDimitry Andric #include "ARMMachineFunctionInfo.h" 118bcb0991SDimitry Andric #include "ARMSubtarget.h" 128bcb0991SDimitry Andric #include "MCTargetDesc/ARMBaseInfo.h" 138bcb0991SDimitry Andric #include "Thumb2InstrInfo.h" 148bcb0991SDimitry Andric #include "llvm/ADT/SmallVector.h" 158bcb0991SDimitry Andric #include "llvm/ADT/Statistic.h" 168bcb0991SDimitry Andric #include "llvm/ADT/StringRef.h" 178bcb0991SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 188bcb0991SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 198bcb0991SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 208bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 218bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 228bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 238bcb0991SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 248bcb0991SDimitry Andric #include "llvm/IR/DebugLoc.h" 258bcb0991SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 265ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 278bcb0991SDimitry Andric #include "llvm/Support/Debug.h" 288bcb0991SDimitry Andric #include <cassert> 298bcb0991SDimitry Andric #include <new> 308bcb0991SDimitry Andric 318bcb0991SDimitry Andric using namespace llvm; 328bcb0991SDimitry Andric 338bcb0991SDimitry Andric #define DEBUG_TYPE "arm-mve-vpt" 348bcb0991SDimitry Andric 358bcb0991SDimitry Andric namespace { 368bcb0991SDimitry Andric class MVEVPTBlock : public MachineFunctionPass { 378bcb0991SDimitry Andric public: 388bcb0991SDimitry Andric static char ID; 395ffd83dbSDimitry Andric const Thumb2InstrInfo *TII; 405ffd83dbSDimitry Andric const TargetRegisterInfo *TRI; 418bcb0991SDimitry Andric 428bcb0991SDimitry Andric MVEVPTBlock() : MachineFunctionPass(ID) {} 438bcb0991SDimitry Andric 448bcb0991SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 458bcb0991SDimitry Andric 468bcb0991SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 478bcb0991SDimitry Andric return MachineFunctionProperties().set( 485ffd83dbSDimitry Andric MachineFunctionProperties::Property::NoVRegs); 498bcb0991SDimitry Andric } 508bcb0991SDimitry Andric 518bcb0991SDimitry Andric StringRef getPassName() const override { 528bcb0991SDimitry Andric return "MVE VPT block insertion pass"; 538bcb0991SDimitry Andric } 548bcb0991SDimitry Andric 558bcb0991SDimitry Andric private: 568bcb0991SDimitry Andric bool InsertVPTBlocks(MachineBasicBlock &MBB); 578bcb0991SDimitry Andric }; 588bcb0991SDimitry Andric 598bcb0991SDimitry Andric char MVEVPTBlock::ID = 0; 608bcb0991SDimitry Andric 618bcb0991SDimitry Andric } // end anonymous namespace 628bcb0991SDimitry Andric 638bcb0991SDimitry Andric INITIALIZE_PASS(MVEVPTBlock, DEBUG_TYPE, "ARM MVE VPT block pass", false, false) 648bcb0991SDimitry Andric 655ffd83dbSDimitry Andric static MachineInstr *findVCMPToFoldIntoVPST(MachineBasicBlock::iterator MI, 665ffd83dbSDimitry Andric const TargetRegisterInfo *TRI, 678bcb0991SDimitry Andric unsigned &NewOpcode) { 685ffd83dbSDimitry Andric // Search backwards to the instruction that defines VPR. This may or not 695ffd83dbSDimitry Andric // be a VCMP, we check that after this loop. If we find another instruction 705ffd83dbSDimitry Andric // that reads cpsr, we return nullptr. 715ffd83dbSDimitry Andric MachineBasicBlock::iterator CmpMI = MI; 725ffd83dbSDimitry Andric while (CmpMI != MI->getParent()->begin()) { 735ffd83dbSDimitry Andric --CmpMI; 745ffd83dbSDimitry Andric if (CmpMI->modifiesRegister(ARM::VPR, TRI)) 755ffd83dbSDimitry Andric break; 765ffd83dbSDimitry Andric if (CmpMI->readsRegister(ARM::VPR, TRI)) 775ffd83dbSDimitry Andric break; 785ffd83dbSDimitry Andric } 795ffd83dbSDimitry Andric 805ffd83dbSDimitry Andric if (CmpMI == MI) 815ffd83dbSDimitry Andric return nullptr; 825ffd83dbSDimitry Andric NewOpcode = VCMPOpcodeToVPT(CmpMI->getOpcode()); 835ffd83dbSDimitry Andric if (NewOpcode == 0) 848bcb0991SDimitry Andric return nullptr; 858bcb0991SDimitry Andric 865ffd83dbSDimitry Andric // Search forward from CmpMI to MI, checking if either register was def'd 875ffd83dbSDimitry Andric if (registerDefinedBetween(CmpMI->getOperand(1).getReg(), std::next(CmpMI), 885ffd83dbSDimitry Andric MI, TRI)) 898bcb0991SDimitry Andric return nullptr; 905ffd83dbSDimitry Andric if (registerDefinedBetween(CmpMI->getOperand(2).getReg(), std::next(CmpMI), 915ffd83dbSDimitry Andric MI, TRI)) 928bcb0991SDimitry Andric return nullptr; 935ffd83dbSDimitry Andric return &*CmpMI; 945ffd83dbSDimitry Andric } 95480093f4SDimitry Andric 965ffd83dbSDimitry Andric // Advances Iter past a block of predicated instructions. 975ffd83dbSDimitry Andric // Returns true if it successfully skipped the whole block of predicated 985ffd83dbSDimitry Andric // instructions. Returns false when it stopped early (due to MaxSteps), or if 995ffd83dbSDimitry Andric // Iter didn't point to a predicated instruction. 1005ffd83dbSDimitry Andric static bool StepOverPredicatedInstrs(MachineBasicBlock::instr_iterator &Iter, 1015ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator EndIter, 1025ffd83dbSDimitry Andric unsigned MaxSteps, 1035ffd83dbSDimitry Andric unsigned &NumInstrsSteppedOver) { 1045ffd83dbSDimitry Andric ARMVCC::VPTCodes NextPred = ARMVCC::None; 1055ffd83dbSDimitry Andric Register PredReg; 1065ffd83dbSDimitry Andric NumInstrsSteppedOver = 0; 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric while (Iter != EndIter) { 1094652422eSDimitry Andric if (Iter->isDebugInstr()) { 1104652422eSDimitry Andric // Skip debug instructions 1114652422eSDimitry Andric ++Iter; 1124652422eSDimitry Andric continue; 1134652422eSDimitry Andric } 1144652422eSDimitry Andric 1155ffd83dbSDimitry Andric NextPred = getVPTInstrPredicate(*Iter, PredReg); 1165ffd83dbSDimitry Andric assert(NextPred != ARMVCC::Else && 1175ffd83dbSDimitry Andric "VPT block pass does not expect Else preds"); 1185ffd83dbSDimitry Andric if (NextPred == ARMVCC::None || MaxSteps == 0) 1195ffd83dbSDimitry Andric break; 1205ffd83dbSDimitry Andric --MaxSteps; 1215ffd83dbSDimitry Andric ++Iter; 1225ffd83dbSDimitry Andric ++NumInstrsSteppedOver; 1235ffd83dbSDimitry Andric }; 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric return NumInstrsSteppedOver != 0 && 1265ffd83dbSDimitry Andric (NextPred == ARMVCC::None || Iter == EndIter); 1275ffd83dbSDimitry Andric } 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric // Returns true if at least one instruction in the range [Iter, End) defines 1305ffd83dbSDimitry Andric // or kills VPR. 1315ffd83dbSDimitry Andric static bool IsVPRDefinedOrKilledByBlock(MachineBasicBlock::iterator Iter, 1325ffd83dbSDimitry Andric MachineBasicBlock::iterator End) { 1335ffd83dbSDimitry Andric for (; Iter != End; ++Iter) 134*0fca6ea1SDimitry Andric if (Iter->definesRegister(ARM::VPR, /*TRI=*/nullptr) || 135*0fca6ea1SDimitry Andric Iter->killsRegister(ARM::VPR, /*TRI=*/nullptr)) 1365ffd83dbSDimitry Andric return true; 1375ffd83dbSDimitry Andric return false; 1385ffd83dbSDimitry Andric } 1395ffd83dbSDimitry Andric 1405ffd83dbSDimitry Andric // Creates a T, TT, TTT or TTTT BlockMask depending on BlockSize. 1415ffd83dbSDimitry Andric static ARM::PredBlockMask GetInitialBlockMask(unsigned BlockSize) { 1425ffd83dbSDimitry Andric switch (BlockSize) { 1435ffd83dbSDimitry Andric case 1: 1445ffd83dbSDimitry Andric return ARM::PredBlockMask::T; 1455ffd83dbSDimitry Andric case 2: 1465ffd83dbSDimitry Andric return ARM::PredBlockMask::TT; 1475ffd83dbSDimitry Andric case 3: 1485ffd83dbSDimitry Andric return ARM::PredBlockMask::TTT; 1495ffd83dbSDimitry Andric case 4: 1505ffd83dbSDimitry Andric return ARM::PredBlockMask::TTTT; 1515ffd83dbSDimitry Andric default: 1525ffd83dbSDimitry Andric llvm_unreachable("Invalid BlockSize!"); 1535ffd83dbSDimitry Andric } 1545ffd83dbSDimitry Andric } 1555ffd83dbSDimitry Andric 1565ffd83dbSDimitry Andric // Given an iterator (Iter) that points at an instruction with a "Then" 1575ffd83dbSDimitry Andric // predicate, tries to create the largest block of continuous predicated 1585ffd83dbSDimitry Andric // instructions possible, and returns the VPT Block Mask of that block. 1595ffd83dbSDimitry Andric // 1605ffd83dbSDimitry Andric // This will try to perform some minor optimization in order to maximize the 1615ffd83dbSDimitry Andric // size of the block. 1625ffd83dbSDimitry Andric static ARM::PredBlockMask 1635ffd83dbSDimitry Andric CreateVPTBlock(MachineBasicBlock::instr_iterator &Iter, 1645ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator EndIter, 1655ffd83dbSDimitry Andric SmallVectorImpl<MachineInstr *> &DeadInstructions) { 1665ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator BlockBeg = Iter; 1675ffd83dbSDimitry Andric (void)BlockBeg; 1685ffd83dbSDimitry Andric assert(getVPTInstrPredicate(*Iter) == ARMVCC::Then && 1695ffd83dbSDimitry Andric "Expected a Predicated Instruction"); 1705ffd83dbSDimitry Andric 1715ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "VPT block created for: "; Iter->dump()); 1725ffd83dbSDimitry Andric 1735ffd83dbSDimitry Andric unsigned BlockSize; 1745ffd83dbSDimitry Andric StepOverPredicatedInstrs(Iter, EndIter, 4, BlockSize); 1755ffd83dbSDimitry Andric 1765ffd83dbSDimitry Andric LLVM_DEBUG(for (MachineBasicBlock::instr_iterator AddedInstIter = 1775ffd83dbSDimitry Andric std::next(BlockBeg); 1785ffd83dbSDimitry Andric AddedInstIter != Iter; ++AddedInstIter) { 1794652422eSDimitry Andric if (AddedInstIter->isDebugInstr()) 1804652422eSDimitry Andric continue; 1815ffd83dbSDimitry Andric dbgs() << " adding: "; 1825ffd83dbSDimitry Andric AddedInstIter->dump(); 1835ffd83dbSDimitry Andric }); 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric // Generate the initial BlockMask 1865ffd83dbSDimitry Andric ARM::PredBlockMask BlockMask = GetInitialBlockMask(BlockSize); 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric // Remove VPNOTs while there's still room in the block, so we can make the 1895ffd83dbSDimitry Andric // largest block possible. 1905ffd83dbSDimitry Andric ARMVCC::VPTCodes CurrentPredicate = ARMVCC::Else; 1915ffd83dbSDimitry Andric while (BlockSize < 4 && Iter != EndIter && 1925ffd83dbSDimitry Andric Iter->getOpcode() == ARM::MVE_VPNOT) { 1935ffd83dbSDimitry Andric 1945ffd83dbSDimitry Andric // Try to skip all of the predicated instructions after the VPNOT, stopping 1955ffd83dbSDimitry Andric // after (4 - BlockSize). If we can't skip them all, stop. 1965ffd83dbSDimitry Andric unsigned ElseInstCnt = 0; 1975ffd83dbSDimitry Andric MachineBasicBlock::instr_iterator VPNOTBlockEndIter = std::next(Iter); 1985ffd83dbSDimitry Andric if (!StepOverPredicatedInstrs(VPNOTBlockEndIter, EndIter, (4 - BlockSize), 1995ffd83dbSDimitry Andric ElseInstCnt)) 2005ffd83dbSDimitry Andric break; 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric // Check if this VPNOT can be removed or not: It can only be removed if at 2035ffd83dbSDimitry Andric // least one of the predicated instruction that follows it kills or sets 2045ffd83dbSDimitry Andric // VPR. 2055ffd83dbSDimitry Andric if (!IsVPRDefinedOrKilledByBlock(Iter, VPNOTBlockEndIter)) 2065ffd83dbSDimitry Andric break; 2075ffd83dbSDimitry Andric 2084652422eSDimitry Andric LLVM_DEBUG(dbgs() << " removing VPNOT: "; Iter->dump()); 2095ffd83dbSDimitry Andric 2105ffd83dbSDimitry Andric // Record the new size of the block 2115ffd83dbSDimitry Andric BlockSize += ElseInstCnt; 2125ffd83dbSDimitry Andric assert(BlockSize <= 4 && "Block is too large!"); 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric // Record the VPNot to remove it later. 2155ffd83dbSDimitry Andric DeadInstructions.push_back(&*Iter); 2165ffd83dbSDimitry Andric ++Iter; 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric // Replace the predicates of the instructions we're adding. 2195ffd83dbSDimitry Andric // Note that we are using "Iter" to iterate over the block so we can update 2205ffd83dbSDimitry Andric // it at the same time. 2215ffd83dbSDimitry Andric for (; Iter != VPNOTBlockEndIter; ++Iter) { 2224652422eSDimitry Andric if (Iter->isDebugInstr()) 2234652422eSDimitry Andric continue; 2244652422eSDimitry Andric 2255ffd83dbSDimitry Andric // Find the register in which the predicate is 2265ffd83dbSDimitry Andric int OpIdx = findFirstVPTPredOperandIdx(*Iter); 2275ffd83dbSDimitry Andric assert(OpIdx != -1); 2285ffd83dbSDimitry Andric 2295ffd83dbSDimitry Andric // Change the predicate and update the mask 2305ffd83dbSDimitry Andric Iter->getOperand(OpIdx).setImm(CurrentPredicate); 2315ffd83dbSDimitry Andric BlockMask = expandPredBlockMask(BlockMask, CurrentPredicate); 2325ffd83dbSDimitry Andric 2335ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " adding : "; Iter->dump()); 2345ffd83dbSDimitry Andric } 2355ffd83dbSDimitry Andric 2365ffd83dbSDimitry Andric CurrentPredicate = 2375ffd83dbSDimitry Andric (CurrentPredicate == ARMVCC::Then ? ARMVCC::Else : ARMVCC::Then); 2385ffd83dbSDimitry Andric } 2395ffd83dbSDimitry Andric return BlockMask; 2408bcb0991SDimitry Andric } 2418bcb0991SDimitry Andric 2428bcb0991SDimitry Andric bool MVEVPTBlock::InsertVPTBlocks(MachineBasicBlock &Block) { 2438bcb0991SDimitry Andric bool Modified = false; 2448bcb0991SDimitry Andric MachineBasicBlock::instr_iterator MBIter = Block.instr_begin(); 2458bcb0991SDimitry Andric MachineBasicBlock::instr_iterator EndIter = Block.instr_end(); 2465ffd83dbSDimitry Andric 2475ffd83dbSDimitry Andric SmallVector<MachineInstr *, 4> DeadInstructions; 2488bcb0991SDimitry Andric 2498bcb0991SDimitry Andric while (MBIter != EndIter) { 2508bcb0991SDimitry Andric MachineInstr *MI = &*MBIter; 2515ffd83dbSDimitry Andric Register PredReg; 2525ffd83dbSDimitry Andric DebugLoc DL = MI->getDebugLoc(); 2538bcb0991SDimitry Andric 2548bcb0991SDimitry Andric ARMVCC::VPTCodes Pred = getVPTInstrPredicate(*MI, PredReg); 2558bcb0991SDimitry Andric 2568bcb0991SDimitry Andric // The idea of the predicate is that None, Then and Else are for use when 2578bcb0991SDimitry Andric // handling assembly language: they correspond to the three possible 2588bcb0991SDimitry Andric // suffixes "", "t" and "e" on the mnemonic. So when instructions are read 2595ffd83dbSDimitry Andric // from assembly source or disassembled from object code, you expect to 2605ffd83dbSDimitry Andric // see a mixture whenever there's a long VPT block. But in code 2615ffd83dbSDimitry Andric // generation, we hope we'll never generate an Else as input to this pass. 2628bcb0991SDimitry Andric assert(Pred != ARMVCC::Else && "VPT block pass does not expect Else preds"); 2638bcb0991SDimitry Andric 2648bcb0991SDimitry Andric if (Pred == ARMVCC::None) { 2658bcb0991SDimitry Andric ++MBIter; 2668bcb0991SDimitry Andric continue; 2678bcb0991SDimitry Andric } 2688bcb0991SDimitry Andric 2695ffd83dbSDimitry Andric ARM::PredBlockMask BlockMask = 2705ffd83dbSDimitry Andric CreateVPTBlock(MBIter, EndIter, DeadInstructions); 2718bcb0991SDimitry Andric 2725ffd83dbSDimitry Andric // Search back for a VCMP that can be folded to create a VPT, or else 2735ffd83dbSDimitry Andric // create a VPST directly 2748bcb0991SDimitry Andric MachineInstrBuilder MIBuilder; 2758bcb0991SDimitry Andric unsigned NewOpcode; 2765ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " final block mask: " << (unsigned)BlockMask << "\n"); 2775ffd83dbSDimitry Andric if (MachineInstr *VCMP = findVCMPToFoldIntoVPST(MI, TRI, NewOpcode)) { 2788bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << " folding VCMP into VPST: "; VCMP->dump()); 2795ffd83dbSDimitry Andric MIBuilder = BuildMI(Block, MI, DL, TII->get(NewOpcode)); 2805ffd83dbSDimitry Andric MIBuilder.addImm((uint64_t)BlockMask); 2818bcb0991SDimitry Andric MIBuilder.add(VCMP->getOperand(1)); 2828bcb0991SDimitry Andric MIBuilder.add(VCMP->getOperand(2)); 2838bcb0991SDimitry Andric MIBuilder.add(VCMP->getOperand(3)); 284e8d8bef9SDimitry Andric 285e8d8bef9SDimitry Andric // We need to remove any kill flags between the original VCMP and the new 286e8d8bef9SDimitry Andric // insertion point. 287e8d8bef9SDimitry Andric for (MachineInstr &MII : 288e8d8bef9SDimitry Andric make_range(VCMP->getIterator(), MI->getIterator())) { 289e8d8bef9SDimitry Andric MII.clearRegisterKills(VCMP->getOperand(1).getReg(), TRI); 290e8d8bef9SDimitry Andric MII.clearRegisterKills(VCMP->getOperand(2).getReg(), TRI); 291e8d8bef9SDimitry Andric } 292e8d8bef9SDimitry Andric 2935ffd83dbSDimitry Andric VCMP->eraseFromParent(); 2948bcb0991SDimitry Andric } else { 2955ffd83dbSDimitry Andric MIBuilder = BuildMI(Block, MI, DL, TII->get(ARM::MVE_VPST)); 2965ffd83dbSDimitry Andric MIBuilder.addImm((uint64_t)BlockMask); 2978bcb0991SDimitry Andric } 2988bcb0991SDimitry Andric 299e8d8bef9SDimitry Andric // Erase all dead instructions (VPNOT's). Do that now so that they do not 300e8d8bef9SDimitry Andric // mess with the bundle creation. 301e8d8bef9SDimitry Andric for (MachineInstr *DeadMI : DeadInstructions) 302e8d8bef9SDimitry Andric DeadMI->eraseFromParent(); 303e8d8bef9SDimitry Andric DeadInstructions.clear(); 304e8d8bef9SDimitry Andric 3058bcb0991SDimitry Andric finalizeBundle( 3068bcb0991SDimitry Andric Block, MachineBasicBlock::instr_iterator(MIBuilder.getInstr()), MBIter); 3078bcb0991SDimitry Andric 3088bcb0991SDimitry Andric Modified = true; 3098bcb0991SDimitry Andric } 310480093f4SDimitry Andric 3118bcb0991SDimitry Andric return Modified; 3128bcb0991SDimitry Andric } 3138bcb0991SDimitry Andric 3148bcb0991SDimitry Andric bool MVEVPTBlock::runOnMachineFunction(MachineFunction &Fn) { 31581ad6265SDimitry Andric const ARMSubtarget &STI = Fn.getSubtarget<ARMSubtarget>(); 3168bcb0991SDimitry Andric 3178bcb0991SDimitry Andric if (!STI.isThumb2() || !STI.hasMVEIntegerOps()) 3188bcb0991SDimitry Andric return false; 3198bcb0991SDimitry Andric 3208bcb0991SDimitry Andric TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo()); 3215ffd83dbSDimitry Andric TRI = STI.getRegisterInfo(); 3228bcb0991SDimitry Andric 3238bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "********** ARM MVE VPT BLOCKS **********\n" 3248bcb0991SDimitry Andric << "********** Function: " << Fn.getName() << '\n'); 3258bcb0991SDimitry Andric 3268bcb0991SDimitry Andric bool Modified = false; 3278bcb0991SDimitry Andric for (MachineBasicBlock &MBB : Fn) 3288bcb0991SDimitry Andric Modified |= InsertVPTBlocks(MBB); 3298bcb0991SDimitry Andric 3308bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "**************************************\n"); 3318bcb0991SDimitry Andric return Modified; 3328bcb0991SDimitry Andric } 3338bcb0991SDimitry Andric 3348bcb0991SDimitry Andric /// createMVEVPTBlock - Returns an instance of the MVE VPT block 3358bcb0991SDimitry Andric /// insertion pass. 3368bcb0991SDimitry Andric FunctionPass *llvm::createMVEVPTBlockPass() { return new MVEVPTBlock(); } 337