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