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