1 //===-- MVEVPTBlockPass.cpp - Insert MVE VPT blocks -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ARM.h" 10 #include "ARMMachineFunctionInfo.h" 11 #include "ARMSubtarget.h" 12 #include "MCTargetDesc/ARMBaseInfo.h" 13 #include "Thumb2InstrInfo.h" 14 #include "llvm/ADT/SmallSet.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/Statistic.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/CodeGen/MachineBasicBlock.h" 19 #include "llvm/CodeGen/MachineFunction.h" 20 #include "llvm/CodeGen/MachineFunctionPass.h" 21 #include "llvm/CodeGen/MachineInstr.h" 22 #include "llvm/CodeGen/MachineInstrBuilder.h" 23 #include "llvm/CodeGen/MachineInstrBundle.h" 24 #include "llvm/CodeGen/MachineOperand.h" 25 #include "llvm/IR/DebugLoc.h" 26 #include "llvm/MC/MCInstrDesc.h" 27 #include "llvm/MC/MCRegisterInfo.h" 28 #include <cassert> 29 #include <new> 30 31 using namespace llvm; 32 33 #define DEBUG_TYPE "arm-mve-vpt" 34 35 namespace { 36 class MVEVPTBlock : public MachineFunctionPass { 37 public: 38 static char ID; 39 const Thumb2InstrInfo *TII; 40 const TargetRegisterInfo *TRI; 41 42 MVEVPTBlock() : MachineFunctionPass(ID) {} 43 44 bool runOnMachineFunction(MachineFunction &Fn) override; 45 46 MachineFunctionProperties getRequiredProperties() const override { 47 return MachineFunctionProperties().set( 48 MachineFunctionProperties::Property::NoVRegs); 49 } 50 51 StringRef getPassName() const override { 52 return "MVE VPT block insertion pass"; 53 } 54 55 private: 56 bool InsertVPTBlocks(MachineBasicBlock &MBB); 57 }; 58 59 char MVEVPTBlock::ID = 0; 60 61 } // end anonymous namespace 62 63 INITIALIZE_PASS(MVEVPTBlock, DEBUG_TYPE, "ARM MVE VPT block pass", false, false) 64 65 enum VPTMaskValue { 66 T = 8, // 0b1000 67 TT = 4, // 0b0100 68 TE = 12, // 0b1100 69 TTT = 2, // 0b0010 70 TTE = 6, // 0b0110 71 TEE = 10, // 0b1010 72 TET = 14, // 0b1110 73 TTTT = 1, // 0b0001 74 TTTE = 3, // 0b0011 75 TTEE = 5, // 0b0101 76 TTET = 7, // 0b0111 77 TEEE = 9, // 0b1001 78 TEET = 11, // 0b1011 79 TETT = 13, // 0b1101 80 TETE = 15 // 0b1111 81 }; 82 83 bool MVEVPTBlock::InsertVPTBlocks(MachineBasicBlock &Block) { 84 bool Modified = false; 85 MachineBasicBlock::instr_iterator MBIter = Block.instr_begin(); 86 MachineBasicBlock::instr_iterator EndIter = Block.instr_end(); 87 88 while (MBIter != EndIter) { 89 MachineInstr *MI = &*MBIter; 90 unsigned PredReg = 0; 91 DebugLoc dl = MI->getDebugLoc(); 92 93 ARMVCC::VPTCodes Pred = getVPTInstrPredicate(*MI, PredReg); 94 95 // The idea of the predicate is that None, Then and Else are for use when 96 // handling assembly language: they correspond to the three possible 97 // suffixes "", "t" and "e" on the mnemonic. So when instructions are read 98 // from assembly source or disassembled from object code, you expect to see 99 // a mixture whenever there's a long VPT block. But in code generation, we 100 // hope we'll never generate an Else as input to this pass. 101 assert(Pred != ARMVCC::Else && "VPT block pass does not expect Else preds"); 102 103 if (Pred == ARMVCC::None) { 104 ++MBIter; 105 continue; 106 } 107 108 LLVM_DEBUG(dbgs() << "VPT block created for: "; MI->dump()); 109 int VPTInstCnt = 1; 110 ARMVCC::VPTCodes NextPred; 111 112 // Look at subsequent instructions, checking if they can be in the same VPT 113 // block. 114 ++MBIter; 115 while (MBIter != EndIter && VPTInstCnt < 4) { 116 NextPred = getVPTInstrPredicate(*MBIter, PredReg); 117 assert(NextPred != ARMVCC::Else && 118 "VPT block pass does not expect Else preds"); 119 if (NextPred != Pred) 120 break; 121 LLVM_DEBUG(dbgs() << " adding : "; MBIter->dump()); 122 ++VPTInstCnt; 123 ++MBIter; 124 }; 125 126 // Create the new VPST 127 MachineInstrBuilder MIBuilder = 128 BuildMI(Block, MI, dl, TII->get(ARM::MVE_VPST)); 129 switch (VPTInstCnt) { 130 case 1: 131 MIBuilder.addImm(VPTMaskValue::T); 132 break; 133 case 2: 134 MIBuilder.addImm(VPTMaskValue::TT); 135 break; 136 case 3: 137 MIBuilder.addImm(VPTMaskValue::TTT); 138 break; 139 case 4: 140 MIBuilder.addImm(VPTMaskValue::TTTT); 141 break; 142 default: 143 llvm_unreachable("Unexpected number of instruction in a VPT block"); 144 }; 145 146 finalizeBundle( 147 Block, MachineBasicBlock::instr_iterator(MIBuilder.getInstr()), MBIter); 148 149 Modified = true; 150 } 151 return Modified; 152 } 153 154 bool MVEVPTBlock::runOnMachineFunction(MachineFunction &Fn) { 155 const ARMSubtarget &STI = 156 static_cast<const ARMSubtarget &>(Fn.getSubtarget()); 157 158 if (!STI.isThumb2() || !STI.hasMVEIntegerOps()) 159 return false; 160 161 TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo()); 162 TRI = STI.getRegisterInfo(); 163 164 LLVM_DEBUG(dbgs() << "********** ARM MVE VPT BLOCKS **********\n" 165 << "********** Function: " << Fn.getName() << '\n'); 166 167 bool Modified = false; 168 for (MachineBasicBlock &MBB : Fn) 169 Modified |= InsertVPTBlocks(MBB); 170 171 LLVM_DEBUG(dbgs() << "**************************************\n"); 172 return Modified; 173 } 174 175 /// createMVEVPTBlock - Returns an instance of the MVE VPT block 176 /// insertion pass. 177 FunctionPass *llvm::createMVEVPTBlockPass() { return new MVEVPTBlock(); } 178