1 //===-- MVETPAndVPTOptimisationsPass.cpp ----------------------------------===// 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 /// \file This pass does a few optimisations related to Tail predicated loops 10 /// and MVE VPT blocks before register allocation is performed. For VPT blocks 11 /// the goal is to maximize the sizes of the blocks that will be created by the 12 /// MVE VPT Block Insertion pass (which runs after register allocation). For 13 /// tail predicated loops we transform the loop into something that will 14 /// hopefully make the backend ARMLowOverheadLoops pass's job easier. 15 /// 16 //===----------------------------------------------------------------------===// 17 18 #include "ARM.h" 19 #include "ARMSubtarget.h" 20 #include "MCTargetDesc/ARMBaseInfo.h" 21 #include "MVETailPredUtils.h" 22 #include "Thumb2InstrInfo.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/CodeGen/MachineBasicBlock.h" 25 #include "llvm/CodeGen/MachineDominators.h" 26 #include "llvm/CodeGen/MachineFunction.h" 27 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/CodeGen/MachineLoopInfo.h" 30 #include "llvm/InitializePasses.h" 31 #include "llvm/Support/Debug.h" 32 #include <cassert> 33 34 using namespace llvm; 35 36 #define DEBUG_TYPE "arm-mve-vpt-opts" 37 38 static cl::opt<bool> 39 MergeEndDec("arm-enable-merge-loopenddec", cl::Hidden, 40 cl::desc("Enable merging Loop End and Dec instructions."), 41 cl::init(true)); 42 43 namespace { 44 class MVETPAndVPTOptimisations : public MachineFunctionPass { 45 public: 46 static char ID; 47 const Thumb2InstrInfo *TII; 48 MachineRegisterInfo *MRI; 49 50 MVETPAndVPTOptimisations() : MachineFunctionPass(ID) {} 51 52 bool runOnMachineFunction(MachineFunction &Fn) override; 53 54 void getAnalysisUsage(AnalysisUsage &AU) const override { 55 AU.addRequired<MachineLoopInfo>(); 56 AU.addPreserved<MachineLoopInfo>(); 57 AU.addRequired<MachineDominatorTree>(); 58 AU.addPreserved<MachineDominatorTree>(); 59 MachineFunctionPass::getAnalysisUsage(AU); 60 } 61 62 StringRef getPassName() const override { 63 return "ARM MVE TailPred and VPT Optimisation Pass"; 64 } 65 66 private: 67 bool MergeLoopEnd(MachineLoop *ML); 68 bool ConvertTailPredLoop(MachineLoop *ML, MachineDominatorTree *DT); 69 MachineInstr &ReplaceRegisterUseWithVPNOT(MachineBasicBlock &MBB, 70 MachineInstr &Instr, 71 MachineOperand &User, 72 Register Target); 73 bool ReduceOldVCCRValueUses(MachineBasicBlock &MBB); 74 bool ReplaceVCMPsByVPNOTs(MachineBasicBlock &MBB); 75 bool ReplaceConstByVPNOTs(MachineBasicBlock &MBB, MachineDominatorTree *DT); 76 bool ConvertVPSEL(MachineBasicBlock &MBB); 77 }; 78 79 char MVETPAndVPTOptimisations::ID = 0; 80 81 } // end anonymous namespace 82 83 INITIALIZE_PASS_BEGIN(MVETPAndVPTOptimisations, DEBUG_TYPE, 84 "ARM MVE TailPred and VPT Optimisations pass", false, 85 false) 86 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) 87 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 88 INITIALIZE_PASS_END(MVETPAndVPTOptimisations, DEBUG_TYPE, 89 "ARM MVE TailPred and VPT Optimisations pass", false, false) 90 91 static MachineInstr *LookThroughCOPY(MachineInstr *MI, 92 MachineRegisterInfo *MRI) { 93 while (MI && MI->getOpcode() == TargetOpcode::COPY && 94 MI->getOperand(1).getReg().isVirtual()) 95 MI = MRI->getVRegDef(MI->getOperand(1).getReg()); 96 return MI; 97 } 98 99 // Given a loop ML, this attempts to find the t2LoopEnd, t2LoopDec and 100 // corresponding PHI that make up a low overhead loop. Only handles 'do' loops 101 // at the moment, returning a t2DoLoopStart in LoopStart. 102 static bool findLoopComponents(MachineLoop *ML, MachineRegisterInfo *MRI, 103 MachineInstr *&LoopStart, MachineInstr *&LoopPhi, 104 MachineInstr *&LoopDec, MachineInstr *&LoopEnd) { 105 MachineBasicBlock *Header = ML->getHeader(); 106 MachineBasicBlock *Latch = ML->getLoopLatch(); 107 if (!Header || !Latch) { 108 LLVM_DEBUG(dbgs() << " no Loop Latch or Header\n"); 109 return false; 110 } 111 112 // Find the loop end from the terminators. 113 LoopEnd = nullptr; 114 for (auto &T : Latch->terminators()) { 115 if (T.getOpcode() == ARM::t2LoopEnd && T.getOperand(1).getMBB() == Header) { 116 LoopEnd = &T; 117 break; 118 } 119 if (T.getOpcode() == ARM::t2LoopEndDec && 120 T.getOperand(2).getMBB() == Header) { 121 LoopEnd = &T; 122 break; 123 } 124 } 125 if (!LoopEnd) { 126 LLVM_DEBUG(dbgs() << " no LoopEnd\n"); 127 return false; 128 } 129 LLVM_DEBUG(dbgs() << " found loop end: " << *LoopEnd); 130 131 // Find the dec from the use of the end. There may be copies between 132 // instructions. We expect the loop to loop like: 133 // $vs = t2DoLoopStart ... 134 // loop: 135 // $vp = phi [ $vs ], [ $vd ] 136 // ... 137 // $vd = t2LoopDec $vp 138 // ... 139 // t2LoopEnd $vd, loop 140 if (LoopEnd->getOpcode() == ARM::t2LoopEndDec) 141 LoopDec = LoopEnd; 142 else { 143 LoopDec = 144 LookThroughCOPY(MRI->getVRegDef(LoopEnd->getOperand(0).getReg()), MRI); 145 if (!LoopDec || LoopDec->getOpcode() != ARM::t2LoopDec) { 146 LLVM_DEBUG(dbgs() << " didn't find LoopDec where we expected!\n"); 147 return false; 148 } 149 } 150 LLVM_DEBUG(dbgs() << " found loop dec: " << *LoopDec); 151 152 LoopPhi = 153 LookThroughCOPY(MRI->getVRegDef(LoopDec->getOperand(1).getReg()), MRI); 154 if (!LoopPhi || LoopPhi->getOpcode() != TargetOpcode::PHI || 155 LoopPhi->getNumOperands() != 5 || 156 (LoopPhi->getOperand(2).getMBB() != Latch && 157 LoopPhi->getOperand(4).getMBB() != Latch)) { 158 LLVM_DEBUG(dbgs() << " didn't find PHI where we expected!\n"); 159 return false; 160 } 161 LLVM_DEBUG(dbgs() << " found loop phi: " << *LoopPhi); 162 163 Register StartReg = LoopPhi->getOperand(2).getMBB() == Latch 164 ? LoopPhi->getOperand(3).getReg() 165 : LoopPhi->getOperand(1).getReg(); 166 LoopStart = LookThroughCOPY(MRI->getVRegDef(StartReg), MRI); 167 if (!LoopStart || LoopStart->getOpcode() != ARM::t2DoLoopStart) { 168 LLVM_DEBUG(dbgs() << " didn't find Start where we expected!\n"); 169 return false; 170 } 171 LLVM_DEBUG(dbgs() << " found loop start: " << *LoopStart); 172 173 return true; 174 } 175 176 // This function converts loops with t2LoopEnd and t2LoopEnd instructions into 177 // a single t2LoopEndDec instruction. To do that it needs to make sure that LR 178 // will be valid to be used for the low overhead loop, which means nothing else 179 // is using LR (especially calls) and there are no superfluous copies in the 180 // loop. The t2LoopEndDec is a branching terminator that produces a value (the 181 // decrement) around the loop edge, which means we need to be careful that they 182 // will be valid to allocate without any spilling. 183 bool MVETPAndVPTOptimisations::MergeLoopEnd(MachineLoop *ML) { 184 if (!MergeEndDec) 185 return false; 186 187 LLVM_DEBUG(dbgs() << "MergeLoopEnd on loop " << ML->getHeader()->getName() 188 << "\n"); 189 190 MachineInstr *LoopEnd, *LoopPhi, *LoopStart, *LoopDec; 191 if (!findLoopComponents(ML, MRI, LoopStart, LoopPhi, LoopDec, LoopEnd)) 192 return false; 193 194 // Check if there is an illegal instruction (a call) in the low overhead loop 195 // and if so revert it now before we get any further. 196 for (MachineBasicBlock *MBB : ML->blocks()) { 197 for (MachineInstr &MI : *MBB) { 198 if (MI.isCall()) { 199 LLVM_DEBUG(dbgs() << "Found call in loop, reverting: " << MI); 200 RevertDoLoopStart(LoopStart, TII); 201 RevertLoopDec(LoopDec, TII); 202 RevertLoopEnd(LoopEnd, TII); 203 return true; 204 } 205 } 206 } 207 208 // Remove any copies from the loop, to ensure the phi that remains is both 209 // simpler and contains no extra uses. Because t2LoopEndDec is a terminator 210 // that cannot spill, we need to be careful what remains in the loop. 211 Register PhiReg = LoopPhi->getOperand(0).getReg(); 212 Register DecReg = LoopDec->getOperand(0).getReg(); 213 Register StartReg = LoopStart->getOperand(0).getReg(); 214 // Ensure the uses are expected, and collect any copies we want to remove. 215 SmallVector<MachineInstr *, 4> Copies; 216 auto CheckUsers = [&Copies](Register BaseReg, 217 ArrayRef<MachineInstr *> ExpectedUsers, 218 MachineRegisterInfo *MRI) { 219 SmallVector<Register, 4> Worklist; 220 Worklist.push_back(BaseReg); 221 while (!Worklist.empty()) { 222 Register Reg = Worklist.pop_back_val(); 223 for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) { 224 if (count(ExpectedUsers, &MI)) 225 continue; 226 if (MI.getOpcode() != TargetOpcode::COPY || 227 !MI.getOperand(0).getReg().isVirtual()) { 228 LLVM_DEBUG(dbgs() << "Extra users of register found: " << MI); 229 return false; 230 } 231 Worklist.push_back(MI.getOperand(0).getReg()); 232 Copies.push_back(&MI); 233 } 234 } 235 return true; 236 }; 237 if (!CheckUsers(PhiReg, {LoopDec}, MRI) || 238 !CheckUsers(DecReg, {LoopPhi, LoopEnd}, MRI) || 239 !CheckUsers(StartReg, {LoopPhi}, MRI)) 240 return false; 241 242 MRI->constrainRegClass(StartReg, &ARM::GPRlrRegClass); 243 MRI->constrainRegClass(PhiReg, &ARM::GPRlrRegClass); 244 MRI->constrainRegClass(DecReg, &ARM::GPRlrRegClass); 245 246 if (LoopPhi->getOperand(2).getMBB() == ML->getLoopLatch()) { 247 LoopPhi->getOperand(3).setReg(StartReg); 248 LoopPhi->getOperand(1).setReg(DecReg); 249 } else { 250 LoopPhi->getOperand(1).setReg(StartReg); 251 LoopPhi->getOperand(3).setReg(DecReg); 252 } 253 254 // Replace the loop dec and loop end as a single instruction. 255 MachineInstrBuilder MI = 256 BuildMI(*LoopEnd->getParent(), *LoopEnd, LoopEnd->getDebugLoc(), 257 TII->get(ARM::t2LoopEndDec), DecReg) 258 .addReg(PhiReg) 259 .add(LoopEnd->getOperand(1)); 260 (void)MI; 261 LLVM_DEBUG(dbgs() << "Merged LoopDec and End into: " << *MI.getInstr()); 262 263 LoopDec->eraseFromParent(); 264 LoopEnd->eraseFromParent(); 265 for (auto *MI : Copies) 266 MI->eraseFromParent(); 267 return true; 268 } 269 270 // Convert t2DoLoopStart to t2DoLoopStartTP if the loop contains VCTP 271 // instructions. This keeps the VCTP count reg operand on the t2DoLoopStartTP 272 // instruction, making the backend ARMLowOverheadLoops passes job of finding the 273 // VCTP operand much simpler. 274 bool MVETPAndVPTOptimisations::ConvertTailPredLoop(MachineLoop *ML, 275 MachineDominatorTree *DT) { 276 LLVM_DEBUG(dbgs() << "ConvertTailPredLoop on loop " 277 << ML->getHeader()->getName() << "\n"); 278 279 // Find some loop components including the LoopEnd/Dec/Start, and any VCTP's 280 // in the loop. 281 MachineInstr *LoopEnd, *LoopPhi, *LoopStart, *LoopDec; 282 if (!findLoopComponents(ML, MRI, LoopStart, LoopPhi, LoopDec, LoopEnd)) 283 return false; 284 if (LoopDec != LoopEnd) 285 return false; 286 287 SmallVector<MachineInstr *, 4> VCTPs; 288 for (MachineBasicBlock *BB : ML->blocks()) 289 for (MachineInstr &MI : *BB) 290 if (isVCTP(&MI)) 291 VCTPs.push_back(&MI); 292 293 if (VCTPs.empty()) { 294 LLVM_DEBUG(dbgs() << " no VCTPs\n"); 295 return false; 296 } 297 298 // Check all VCTPs are the same. 299 MachineInstr *FirstVCTP = *VCTPs.begin(); 300 for (MachineInstr *VCTP : VCTPs) { 301 LLVM_DEBUG(dbgs() << " with VCTP " << *VCTP); 302 if (VCTP->getOpcode() != FirstVCTP->getOpcode() || 303 VCTP->getOperand(0).getReg() != FirstVCTP->getOperand(0).getReg()) { 304 LLVM_DEBUG(dbgs() << " VCTP's are not identical\n"); 305 return false; 306 } 307 } 308 309 // Check for the register being used can be setup before the loop. We expect 310 // this to be: 311 // $vx = ... 312 // loop: 313 // $vp = PHI [ $vx ], [ $vd ] 314 // .. 315 // $vpr = VCTP $vp 316 // .. 317 // $vd = t2SUBri $vp, #n 318 // .. 319 Register CountReg = FirstVCTP->getOperand(1).getReg(); 320 if (!CountReg.isVirtual()) { 321 LLVM_DEBUG(dbgs() << " cannot determine VCTP PHI\n"); 322 return false; 323 } 324 MachineInstr *Phi = LookThroughCOPY(MRI->getVRegDef(CountReg), MRI); 325 if (!Phi || Phi->getOpcode() != TargetOpcode::PHI || 326 Phi->getNumOperands() != 5 || 327 (Phi->getOperand(2).getMBB() != ML->getLoopLatch() && 328 Phi->getOperand(4).getMBB() != ML->getLoopLatch())) { 329 LLVM_DEBUG(dbgs() << " cannot determine VCTP Count\n"); 330 return false; 331 } 332 CountReg = Phi->getOperand(2).getMBB() == ML->getLoopLatch() 333 ? Phi->getOperand(3).getReg() 334 : Phi->getOperand(1).getReg(); 335 336 // Replace the t2DoLoopStart with the t2DoLoopStartTP, move it to the end of 337 // the preheader and add the new CountReg to it. We attempt to place it late 338 // in the preheader, but may need to move that earlier based on uses. 339 MachineBasicBlock *MBB = LoopStart->getParent(); 340 MachineBasicBlock::iterator InsertPt = MBB->getFirstTerminator(); 341 for (MachineInstr &Use : 342 MRI->use_instructions(LoopStart->getOperand(0).getReg())) 343 if ((InsertPt != MBB->end() && !DT->dominates(&*InsertPt, &Use)) || 344 !DT->dominates(ML->getHeader(), Use.getParent())) { 345 LLVM_DEBUG(dbgs() << " InsertPt could not be a terminator!\n"); 346 return false; 347 } 348 349 MachineInstrBuilder MI = BuildMI(*MBB, InsertPt, LoopStart->getDebugLoc(), 350 TII->get(ARM::t2DoLoopStartTP)) 351 .add(LoopStart->getOperand(0)) 352 .add(LoopStart->getOperand(1)) 353 .addReg(CountReg); 354 (void)MI; 355 LLVM_DEBUG(dbgs() << "Replacing " << *LoopStart << " with " 356 << *MI.getInstr()); 357 MRI->constrainRegClass(CountReg, &ARM::rGPRRegClass); 358 LoopStart->eraseFromParent(); 359 360 return true; 361 } 362 363 // Returns true if Opcode is any VCMP Opcode. 364 static bool IsVCMP(unsigned Opcode) { return VCMPOpcodeToVPT(Opcode) != 0; } 365 366 // Returns true if a VCMP with this Opcode can have its operands swapped. 367 // There is 2 kind of VCMP that can't have their operands swapped: Float VCMPs, 368 // and VCMPr instructions (since the r is always on the right). 369 static bool CanHaveSwappedOperands(unsigned Opcode) { 370 switch (Opcode) { 371 default: 372 return true; 373 case ARM::MVE_VCMPf32: 374 case ARM::MVE_VCMPf16: 375 case ARM::MVE_VCMPf32r: 376 case ARM::MVE_VCMPf16r: 377 case ARM::MVE_VCMPi8r: 378 case ARM::MVE_VCMPi16r: 379 case ARM::MVE_VCMPi32r: 380 case ARM::MVE_VCMPu8r: 381 case ARM::MVE_VCMPu16r: 382 case ARM::MVE_VCMPu32r: 383 case ARM::MVE_VCMPs8r: 384 case ARM::MVE_VCMPs16r: 385 case ARM::MVE_VCMPs32r: 386 return false; 387 } 388 } 389 390 // Returns the CondCode of a VCMP Instruction. 391 static ARMCC::CondCodes GetCondCode(MachineInstr &Instr) { 392 assert(IsVCMP(Instr.getOpcode()) && "Inst must be a VCMP"); 393 return ARMCC::CondCodes(Instr.getOperand(3).getImm()); 394 } 395 396 // Returns true if Cond is equivalent to a VPNOT instruction on the result of 397 // Prev. Cond and Prev must be VCMPs. 398 static bool IsVPNOTEquivalent(MachineInstr &Cond, MachineInstr &Prev) { 399 assert(IsVCMP(Cond.getOpcode()) && IsVCMP(Prev.getOpcode())); 400 401 // Opcodes must match. 402 if (Cond.getOpcode() != Prev.getOpcode()) 403 return false; 404 405 MachineOperand &CondOP1 = Cond.getOperand(1), &CondOP2 = Cond.getOperand(2); 406 MachineOperand &PrevOP1 = Prev.getOperand(1), &PrevOP2 = Prev.getOperand(2); 407 408 // If the VCMP has the opposite condition with the same operands, we can 409 // replace it with a VPNOT 410 ARMCC::CondCodes ExpectedCode = GetCondCode(Cond); 411 ExpectedCode = ARMCC::getOppositeCondition(ExpectedCode); 412 if (ExpectedCode == GetCondCode(Prev)) 413 if (CondOP1.isIdenticalTo(PrevOP1) && CondOP2.isIdenticalTo(PrevOP2)) 414 return true; 415 // Check again with operands swapped if possible 416 if (!CanHaveSwappedOperands(Cond.getOpcode())) 417 return false; 418 ExpectedCode = ARMCC::getSwappedCondition(ExpectedCode); 419 return ExpectedCode == GetCondCode(Prev) && CondOP1.isIdenticalTo(PrevOP2) && 420 CondOP2.isIdenticalTo(PrevOP1); 421 } 422 423 // Returns true if Instr writes to VCCR. 424 static bool IsWritingToVCCR(MachineInstr &Instr) { 425 if (Instr.getNumOperands() == 0) 426 return false; 427 MachineOperand &Dst = Instr.getOperand(0); 428 if (!Dst.isReg()) 429 return false; 430 Register DstReg = Dst.getReg(); 431 if (!DstReg.isVirtual()) 432 return false; 433 MachineRegisterInfo &RegInfo = Instr.getMF()->getRegInfo(); 434 const TargetRegisterClass *RegClass = RegInfo.getRegClassOrNull(DstReg); 435 return RegClass && (RegClass->getID() == ARM::VCCRRegClassID); 436 } 437 438 // Transforms 439 // <Instr that uses %A ('User' Operand)> 440 // Into 441 // %K = VPNOT %Target 442 // <Instr that uses %K ('User' Operand)> 443 // And returns the newly inserted VPNOT. 444 // This optimization is done in the hopes of preventing spills/reloads of VPR by 445 // reducing the number of VCCR values with overlapping lifetimes. 446 MachineInstr &MVETPAndVPTOptimisations::ReplaceRegisterUseWithVPNOT( 447 MachineBasicBlock &MBB, MachineInstr &Instr, MachineOperand &User, 448 Register Target) { 449 Register NewResult = MRI->createVirtualRegister(MRI->getRegClass(Target)); 450 451 MachineInstrBuilder MIBuilder = 452 BuildMI(MBB, &Instr, Instr.getDebugLoc(), TII->get(ARM::MVE_VPNOT)) 453 .addDef(NewResult) 454 .addReg(Target); 455 addUnpredicatedMveVpredNOp(MIBuilder); 456 457 // Make the user use NewResult instead, and clear its kill flag. 458 User.setReg(NewResult); 459 User.setIsKill(false); 460 461 LLVM_DEBUG(dbgs() << " Inserting VPNOT (for spill prevention): "; 462 MIBuilder.getInstr()->dump()); 463 464 return *MIBuilder.getInstr(); 465 } 466 467 // Moves a VPNOT before its first user if an instruction that uses Reg is found 468 // in-between the VPNOT and its user. 469 // Returns true if there is at least one user of the VPNOT in the block. 470 static bool MoveVPNOTBeforeFirstUser(MachineBasicBlock &MBB, 471 MachineBasicBlock::iterator Iter, 472 Register Reg) { 473 assert(Iter->getOpcode() == ARM::MVE_VPNOT && "Not a VPNOT!"); 474 assert(getVPTInstrPredicate(*Iter) == ARMVCC::None && 475 "The VPNOT cannot be predicated"); 476 477 MachineInstr &VPNOT = *Iter; 478 Register VPNOTResult = VPNOT.getOperand(0).getReg(); 479 Register VPNOTOperand = VPNOT.getOperand(1).getReg(); 480 481 // Whether the VPNOT will need to be moved, and whether we found a user of the 482 // VPNOT. 483 bool MustMove = false, HasUser = false; 484 MachineOperand *VPNOTOperandKiller = nullptr; 485 for (; Iter != MBB.end(); ++Iter) { 486 if (MachineOperand *MO = 487 Iter->findRegisterUseOperand(VPNOTOperand, /*isKill*/ true)) { 488 // If we find the operand that kills the VPNOTOperand's result, save it. 489 VPNOTOperandKiller = MO; 490 } 491 492 if (Iter->findRegisterUseOperandIdx(Reg) != -1) { 493 MustMove = true; 494 continue; 495 } 496 497 if (Iter->findRegisterUseOperandIdx(VPNOTResult) == -1) 498 continue; 499 500 HasUser = true; 501 if (!MustMove) 502 break; 503 504 // Move the VPNOT right before Iter 505 LLVM_DEBUG(dbgs() << "Moving: "; VPNOT.dump(); dbgs() << " Before: "; 506 Iter->dump()); 507 MBB.splice(Iter, &MBB, VPNOT.getIterator()); 508 // If we move the instr, and its operand was killed earlier, remove the kill 509 // flag. 510 if (VPNOTOperandKiller) 511 VPNOTOperandKiller->setIsKill(false); 512 513 break; 514 } 515 return HasUser; 516 } 517 518 // This optimisation attempts to reduce the number of overlapping lifetimes of 519 // VCCR values by replacing uses of old VCCR values with VPNOTs. For example, 520 // this replaces 521 // %A:vccr = (something) 522 // %B:vccr = VPNOT %A 523 // %Foo = (some op that uses %B) 524 // %Bar = (some op that uses %A) 525 // With 526 // %A:vccr = (something) 527 // %B:vccr = VPNOT %A 528 // %Foo = (some op that uses %B) 529 // %TMP2:vccr = VPNOT %B 530 // %Bar = (some op that uses %A) 531 bool MVETPAndVPTOptimisations::ReduceOldVCCRValueUses(MachineBasicBlock &MBB) { 532 MachineBasicBlock::iterator Iter = MBB.begin(), End = MBB.end(); 533 SmallVector<MachineInstr *, 4> DeadInstructions; 534 bool Modified = false; 535 536 while (Iter != End) { 537 Register VCCRValue, OppositeVCCRValue; 538 // The first loop looks for 2 unpredicated instructions: 539 // %A:vccr = (instr) ; A is stored in VCCRValue 540 // %B:vccr = VPNOT %A ; B is stored in OppositeVCCRValue 541 for (; Iter != End; ++Iter) { 542 // We're only interested in unpredicated instructions that write to VCCR. 543 if (!IsWritingToVCCR(*Iter) || 544 getVPTInstrPredicate(*Iter) != ARMVCC::None) 545 continue; 546 Register Dst = Iter->getOperand(0).getReg(); 547 548 // If we already have a VCCRValue, and this is a VPNOT on VCCRValue, we've 549 // found what we were looking for. 550 if (VCCRValue && Iter->getOpcode() == ARM::MVE_VPNOT && 551 Iter->findRegisterUseOperandIdx(VCCRValue) != -1) { 552 // Move the VPNOT closer to its first user if needed, and ignore if it 553 // has no users. 554 if (!MoveVPNOTBeforeFirstUser(MBB, Iter, VCCRValue)) 555 continue; 556 557 OppositeVCCRValue = Dst; 558 ++Iter; 559 break; 560 } 561 562 // Else, just set VCCRValue. 563 VCCRValue = Dst; 564 } 565 566 // If the first inner loop didn't find anything, stop here. 567 if (Iter == End) 568 break; 569 570 assert(VCCRValue && OppositeVCCRValue && 571 "VCCRValue and OppositeVCCRValue shouldn't be empty if the loop " 572 "stopped before the end of the block!"); 573 assert(VCCRValue != OppositeVCCRValue && 574 "VCCRValue should not be equal to OppositeVCCRValue!"); 575 576 // LastVPNOTResult always contains the same value as OppositeVCCRValue. 577 Register LastVPNOTResult = OppositeVCCRValue; 578 579 // This second loop tries to optimize the remaining instructions. 580 for (; Iter != End; ++Iter) { 581 bool IsInteresting = false; 582 583 if (MachineOperand *MO = Iter->findRegisterUseOperand(VCCRValue)) { 584 IsInteresting = true; 585 586 // - If the instruction is a VPNOT, it can be removed, and we can just 587 // replace its uses with LastVPNOTResult. 588 // - Else, insert a new VPNOT on LastVPNOTResult to recompute VCCRValue. 589 if (Iter->getOpcode() == ARM::MVE_VPNOT) { 590 Register Result = Iter->getOperand(0).getReg(); 591 592 MRI->replaceRegWith(Result, LastVPNOTResult); 593 DeadInstructions.push_back(&*Iter); 594 Modified = true; 595 596 LLVM_DEBUG(dbgs() 597 << "Replacing all uses of '" << printReg(Result) 598 << "' with '" << printReg(LastVPNOTResult) << "'\n"); 599 } else { 600 MachineInstr &VPNOT = 601 ReplaceRegisterUseWithVPNOT(MBB, *Iter, *MO, LastVPNOTResult); 602 Modified = true; 603 604 LastVPNOTResult = VPNOT.getOperand(0).getReg(); 605 std::swap(VCCRValue, OppositeVCCRValue); 606 607 LLVM_DEBUG(dbgs() << "Replacing use of '" << printReg(VCCRValue) 608 << "' with '" << printReg(LastVPNOTResult) 609 << "' in instr: " << *Iter); 610 } 611 } else { 612 // If the instr uses OppositeVCCRValue, make it use LastVPNOTResult 613 // instead as they contain the same value. 614 if (MachineOperand *MO = 615 Iter->findRegisterUseOperand(OppositeVCCRValue)) { 616 IsInteresting = true; 617 618 // This is pointless if LastVPNOTResult == OppositeVCCRValue. 619 if (LastVPNOTResult != OppositeVCCRValue) { 620 LLVM_DEBUG(dbgs() << "Replacing usage of '" 621 << printReg(OppositeVCCRValue) << "' with '" 622 << printReg(LastVPNOTResult) << " for instr: "; 623 Iter->dump()); 624 MO->setReg(LastVPNOTResult); 625 Modified = true; 626 } 627 628 MO->setIsKill(false); 629 } 630 631 // If this is an unpredicated VPNOT on 632 // LastVPNOTResult/OppositeVCCRValue, we can act like we inserted it. 633 if (Iter->getOpcode() == ARM::MVE_VPNOT && 634 getVPTInstrPredicate(*Iter) == ARMVCC::None) { 635 Register VPNOTOperand = Iter->getOperand(1).getReg(); 636 if (VPNOTOperand == LastVPNOTResult || 637 VPNOTOperand == OppositeVCCRValue) { 638 IsInteresting = true; 639 640 std::swap(VCCRValue, OppositeVCCRValue); 641 LastVPNOTResult = Iter->getOperand(0).getReg(); 642 } 643 } 644 } 645 646 // If this instruction was not interesting, and it writes to VCCR, stop. 647 if (!IsInteresting && IsWritingToVCCR(*Iter)) 648 break; 649 } 650 } 651 652 for (MachineInstr *DeadInstruction : DeadInstructions) 653 DeadInstruction->eraseFromParent(); 654 655 return Modified; 656 } 657 658 // This optimisation replaces VCMPs with VPNOTs when they are equivalent. 659 bool MVETPAndVPTOptimisations::ReplaceVCMPsByVPNOTs(MachineBasicBlock &MBB) { 660 SmallVector<MachineInstr *, 4> DeadInstructions; 661 662 // The last VCMP that we have seen and that couldn't be replaced. 663 // This is reset when an instruction that writes to VCCR/VPR is found, or when 664 // a VCMP is replaced with a VPNOT. 665 // We'll only replace VCMPs with VPNOTs when this is not null, and when the 666 // current VCMP is the opposite of PrevVCMP. 667 MachineInstr *PrevVCMP = nullptr; 668 // If we find an instruction that kills the result of PrevVCMP, we save the 669 // operand here to remove the kill flag in case we need to use PrevVCMP's 670 // result. 671 MachineOperand *PrevVCMPResultKiller = nullptr; 672 673 for (MachineInstr &Instr : MBB.instrs()) { 674 if (PrevVCMP) { 675 if (MachineOperand *MO = Instr.findRegisterUseOperand( 676 PrevVCMP->getOperand(0).getReg(), /*isKill*/ true)) { 677 // If we come accross the instr that kills PrevVCMP's result, record it 678 // so we can remove the kill flag later if we need to. 679 PrevVCMPResultKiller = MO; 680 } 681 } 682 683 // Ignore predicated instructions. 684 if (getVPTInstrPredicate(Instr) != ARMVCC::None) 685 continue; 686 687 // Only look at VCMPs 688 if (!IsVCMP(Instr.getOpcode())) { 689 // If the instruction writes to VCCR, forget the previous VCMP. 690 if (IsWritingToVCCR(Instr)) 691 PrevVCMP = nullptr; 692 continue; 693 } 694 695 if (!PrevVCMP || !IsVPNOTEquivalent(Instr, *PrevVCMP)) { 696 PrevVCMP = &Instr; 697 continue; 698 } 699 700 // The register containing the result of the VCMP that we're going to 701 // replace. 702 Register PrevVCMPResultReg = PrevVCMP->getOperand(0).getReg(); 703 704 // Build a VPNOT to replace the VCMP, reusing its operands. 705 MachineInstrBuilder MIBuilder = 706 BuildMI(MBB, &Instr, Instr.getDebugLoc(), TII->get(ARM::MVE_VPNOT)) 707 .add(Instr.getOperand(0)) 708 .addReg(PrevVCMPResultReg); 709 addUnpredicatedMveVpredNOp(MIBuilder); 710 LLVM_DEBUG(dbgs() << "Inserting VPNOT (to replace VCMP): "; 711 MIBuilder.getInstr()->dump(); dbgs() << " Removed VCMP: "; 712 Instr.dump()); 713 714 // If we found an instruction that uses, and kills PrevVCMP's result, 715 // remove the kill flag. 716 if (PrevVCMPResultKiller) 717 PrevVCMPResultKiller->setIsKill(false); 718 719 // Finally, mark the old VCMP for removal and reset 720 // PrevVCMP/PrevVCMPResultKiller. 721 DeadInstructions.push_back(&Instr); 722 PrevVCMP = nullptr; 723 PrevVCMPResultKiller = nullptr; 724 } 725 726 for (MachineInstr *DeadInstruction : DeadInstructions) 727 DeadInstruction->eraseFromParent(); 728 729 return !DeadInstructions.empty(); 730 } 731 732 bool MVETPAndVPTOptimisations::ReplaceConstByVPNOTs(MachineBasicBlock &MBB, 733 MachineDominatorTree *DT) { 734 // Scan through the block, looking for instructions that use constants moves 735 // into VPR that are the negative of one another. These are expected to be 736 // COPY's to VCCRRegClass, from a t2MOVi or t2MOVi16. The last seen constant 737 // mask is kept it or and VPNOT's of it are added or reused as we scan through 738 // the function. 739 unsigned LastVPTImm = 0; 740 Register LastVPTReg = 0; 741 SmallSet<MachineInstr *, 4> DeadInstructions; 742 743 for (MachineInstr &Instr : MBB.instrs()) { 744 // Look for predicated MVE instructions. 745 int PIdx = llvm::findFirstVPTPredOperandIdx(Instr); 746 if (PIdx == -1) 747 continue; 748 Register VPR = Instr.getOperand(PIdx + 1).getReg(); 749 if (!VPR.isVirtual()) 750 continue; 751 752 // From that we are looking for an instruction like %11:vccr = COPY %9:rgpr. 753 MachineInstr *Copy = MRI->getVRegDef(VPR); 754 if (!Copy || Copy->getOpcode() != TargetOpcode::COPY || 755 !Copy->getOperand(1).getReg().isVirtual() || 756 MRI->getRegClass(Copy->getOperand(1).getReg()) == &ARM::VCCRRegClass) { 757 LastVPTReg = 0; 758 continue; 759 } 760 Register GPR = Copy->getOperand(1).getReg(); 761 762 // Find the Immediate used by the copy. 763 auto getImm = [&](Register GPR) -> unsigned { 764 MachineInstr *Def = MRI->getVRegDef(GPR); 765 if (Def && (Def->getOpcode() == ARM::t2MOVi || 766 Def->getOpcode() == ARM::t2MOVi16)) 767 return Def->getOperand(1).getImm(); 768 return -1U; 769 }; 770 unsigned Imm = getImm(GPR); 771 if (Imm == -1U) { 772 LastVPTReg = 0; 773 continue; 774 } 775 776 unsigned NotImm = ~Imm & 0xffff; 777 if (LastVPTReg != 0 && LastVPTReg != VPR && LastVPTImm == Imm) { 778 Instr.getOperand(PIdx + 1).setReg(LastVPTReg); 779 if (MRI->use_empty(VPR)) { 780 DeadInstructions.insert(Copy); 781 if (MRI->hasOneUse(GPR)) 782 DeadInstructions.insert(MRI->getVRegDef(GPR)); 783 } 784 LLVM_DEBUG(dbgs() << "Reusing predicate: in " << Instr); 785 } else if (LastVPTReg != 0 && LastVPTImm == NotImm) { 786 // We have found the not of a previous constant. Create a VPNot of the 787 // earlier predicate reg and use it instead of the copy. 788 Register NewVPR = MRI->createVirtualRegister(&ARM::VCCRRegClass); 789 auto VPNot = BuildMI(MBB, &Instr, Instr.getDebugLoc(), 790 TII->get(ARM::MVE_VPNOT), NewVPR) 791 .addReg(LastVPTReg); 792 addUnpredicatedMveVpredNOp(VPNot); 793 794 // Use the new register and check if the def is now dead. 795 Instr.getOperand(PIdx + 1).setReg(NewVPR); 796 if (MRI->use_empty(VPR)) { 797 DeadInstructions.insert(Copy); 798 if (MRI->hasOneUse(GPR)) 799 DeadInstructions.insert(MRI->getVRegDef(GPR)); 800 } 801 LLVM_DEBUG(dbgs() << "Adding VPNot: " << *VPNot << " to replace use at " 802 << Instr); 803 VPR = NewVPR; 804 } 805 806 LastVPTImm = Imm; 807 LastVPTReg = VPR; 808 } 809 810 for (MachineInstr *DI : DeadInstructions) 811 DI->eraseFromParent(); 812 813 return !DeadInstructions.empty(); 814 } 815 816 // Replace VPSEL with a predicated VMOV in blocks with a VCTP. This is a 817 // somewhat blunt approximation to allow tail predicated with vpsel 818 // instructions. We turn a vselect into a VPSEL in ISEL, but they have slightly 819 // different semantics under tail predication. Until that is modelled we just 820 // convert to a VMOVT (via a predicated VORR) instead. 821 bool MVETPAndVPTOptimisations::ConvertVPSEL(MachineBasicBlock &MBB) { 822 bool HasVCTP = false; 823 SmallVector<MachineInstr *, 4> DeadInstructions; 824 825 for (MachineInstr &MI : MBB.instrs()) { 826 if (isVCTP(&MI)) { 827 HasVCTP = true; 828 continue; 829 } 830 831 if (!HasVCTP || MI.getOpcode() != ARM::MVE_VPSEL) 832 continue; 833 834 MachineInstrBuilder MIBuilder = 835 BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(ARM::MVE_VORR)) 836 .add(MI.getOperand(0)) 837 .add(MI.getOperand(1)) 838 .add(MI.getOperand(1)) 839 .addImm(ARMVCC::Then) 840 .add(MI.getOperand(4)) 841 .add(MI.getOperand(2)); 842 // Silence unused variable warning in release builds. 843 (void)MIBuilder; 844 LLVM_DEBUG(dbgs() << "Replacing VPSEL: "; MI.dump(); 845 dbgs() << " with VMOVT: "; MIBuilder.getInstr()->dump()); 846 DeadInstructions.push_back(&MI); 847 } 848 849 for (MachineInstr *DeadInstruction : DeadInstructions) 850 DeadInstruction->eraseFromParent(); 851 852 return !DeadInstructions.empty(); 853 } 854 855 bool MVETPAndVPTOptimisations::runOnMachineFunction(MachineFunction &Fn) { 856 const ARMSubtarget &STI = 857 static_cast<const ARMSubtarget &>(Fn.getSubtarget()); 858 859 if (!STI.isThumb2() || !STI.hasLOB()) 860 return false; 861 862 TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo()); 863 MRI = &Fn.getRegInfo(); 864 MachineLoopInfo *MLI = &getAnalysis<MachineLoopInfo>(); 865 MachineDominatorTree *DT = &getAnalysis<MachineDominatorTree>(); 866 867 LLVM_DEBUG(dbgs() << "********** ARM MVE VPT Optimisations **********\n" 868 << "********** Function: " << Fn.getName() << '\n'); 869 870 bool Modified = false; 871 for (MachineLoop *ML : MLI->getBase().getLoopsInPreorder()) { 872 Modified |= MergeLoopEnd(ML); 873 Modified |= ConvertTailPredLoop(ML, DT); 874 } 875 876 for (MachineBasicBlock &MBB : Fn) { 877 Modified |= ReplaceConstByVPNOTs(MBB, DT); 878 Modified |= ReplaceVCMPsByVPNOTs(MBB); 879 Modified |= ReduceOldVCCRValueUses(MBB); 880 Modified |= ConvertVPSEL(MBB); 881 } 882 883 LLVM_DEBUG(dbgs() << "**************************************\n"); 884 return Modified; 885 } 886 887 /// createMVETPAndVPTOptimisationsPass 888 FunctionPass *llvm::createMVETPAndVPTOptimisationsPass() { 889 return new MVETPAndVPTOptimisations(); 890 } 891