Index: llvm/lib/Target/ARM/ARM.h =================================================================== --- llvm/lib/Target/ARM/ARM.h +++ llvm/lib/Target/ARM/ARM.h @@ -46,6 +46,7 @@ FunctionPass *createARMConstantIslandPass(); FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); +FunctionPass *createMVEVPTBlockPass(); FunctionPass *createARMOptimizeBarriersPass(); FunctionPass *createThumb2SizeReductionPass( std::function Ftor = nullptr); Index: llvm/lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -508,6 +508,7 @@ return !MF.getSubtarget().isThumb1Only(); })); } + addPass(createMVEVPTBlockPass()); addPass(createThumb2ITBlockPass()); } Index: llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp =================================================================== --- llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp +++ llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp @@ -318,3 +318,89 @@ FunctionPass *llvm::createThumb2ITBlockPass() { return new Thumb2ITBlockPass(); } + +#undef DEBUG_TYPE +#define DEBUG_TYPE "mve-vpt" + +namespace { + class MVEVPTBlockPass : public MachineFunctionPass { + public: + static char ID; + const Thumb2InstrInfo *TII; + const TargetRegisterInfo *TRI; + + MVEVPTBlockPass() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &Fn) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + StringRef getPassName() const override { + return "MVE VPT blocks insertion pass"; + } + + private: + bool InsertVPTBlocks(MachineBasicBlock &MBB); + }; + + char MVEVPTBlockPass::ID = 0; + +} // end anonymous namespace + +bool MVEVPTBlockPass::InsertVPTBlocks(MachineBasicBlock &Block) { + bool Modified = false; + MachineBasicBlock::iterator MBIter = Block.begin(); + MachineBasicBlock::iterator EndIter = Block.end(); + + while (MBIter != EndIter) { + MachineInstr *MI = &*MBIter; + unsigned PredReg = 0; + DebugLoc dl = MI->getDebugLoc(); + + if (getVPTInstrPredicate(*MI, PredReg) != ARMVCC::None) { + MachineInstrBuilder MIBuilder = + BuildMI(Block, MBIter, dl, TII->get(ARM::t2VPST)); + MachineInstr *LastITMI = MI; + MachineBasicBlock::iterator InsertPos = MIBuilder.getInstr(); + + const unsigned Mask = 8U; + MIBuilder.addImm(Mask); + + finalizeBundle(Block, InsertPos.getInstrIterator(), + ++LastITMI->getIterator()); + Modified = true; + } + ++MBIter; + } + return Modified; +} + +bool MVEVPTBlockPass::runOnMachineFunction(MachineFunction &Fn) { + const ARMSubtarget &STI = + static_cast(Fn.getSubtarget()); + + if (!STI.isThumb2() || !STI.hasMVEIntegerOps()) + return false; + + TII = static_cast(STI.getInstrInfo()); + TRI = STI.getRegisterInfo(); + + LLVM_DEBUG(dbgs() << "********** ARM MVE VPT BLOCKS **********\n" + << "********** Function: " << Fn.getName() << '\n'); + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;) { + MachineBasicBlock &MBB = *MFI; + ++MFI; + Modified |= InsertVPTBlocks(MBB); + } + LLVM_DEBUG(dbgs() << "**************************************\n"); + return Modified; +} + +/// createMVEVPTBlockPass - Returns an instance of the MVE VPT block +/// insertion pass. +FunctionPass *llvm::createMVEVPTBlockPass() { return new MVEVPTBlockPass(); } Index: llvm/lib/Target/ARM/Thumb2InstrInfo.h =================================================================== --- llvm/lib/Target/ARM/Thumb2InstrInfo.h +++ llvm/lib/Target/ARM/Thumb2InstrInfo.h @@ -68,6 +68,12 @@ /// to llvm::getInstrPredicate except it returns AL for conditional branch /// instructions which are "predicated", but are not in IT blocks. ARMCC::CondCodes getITInstrPredicate(const MachineInstr &MI, unsigned &PredReg); + +// getVPTInstrPredicate: VPT analogue of that, plus a helper function +// corresponding to MachineInstr::findFirstPredOperandIdx. +int findFirstVPTPredOperandIdx(const MachineInstr &MI); +ARMVCC::VPTCodes getVPTInstrPredicate(const MachineInstr &MI, + unsigned &PredReg); } #endif Index: llvm/lib/Target/ARM/Thumb2InstrInfo.cpp =================================================================== --- llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -685,3 +685,28 @@ return ARMCC::AL; return getInstrPredicate(MI, PredReg); } + +int llvm::findFirstVPTPredOperandIdx(const MachineInstr &MI) { + const MCInstrDesc &MCID = MI.getDesc(); + + if (!MCID.OpInfo) + return -1; + + for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) + if (ARM::isVpred(MCID.OpInfo[i].OperandType)) + return i; + + return -1; +} + +ARMVCC::VPTCodes llvm::getVPTInstrPredicate(const MachineInstr &MI, + unsigned &PredReg) { + int PIdx = findFirstVPTPredOperandIdx(MI); + if (PIdx == -1) { + PredReg = 0; + return ARMVCC::None; + } + + PredReg = MI.getOperand(PIdx+1).getReg(); + return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm(); +} Index: llvm/test/CodeGen/ARM/O3-pipeline.ll =================================================================== --- llvm/test/CodeGen/ARM/O3-pipeline.ll +++ llvm/test/CodeGen/ARM/O3-pipeline.ll @@ -125,6 +125,7 @@ ; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: If Converter +; CHECK-NEXT: MVE VPT block insertion pass ; CHECK-NEXT: Thumb IT blocks insertion pass ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Machine Natural Loop Construction