1 //===-- SILowerI1Copies.cpp - Lower I1 Copies -----------------------------===// 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 // This pass lowers all occurrences of i1 values (with a vreg_1 register class) 10 // to lane masks (32 / 64-bit scalar registers). The pass assumes machine SSA 11 // form and a wave-level control flow graph. 12 // 13 // Before this pass, values that are semantically i1 and are defined and used 14 // within the same basic block are already represented as lane masks in scalar 15 // registers. However, values that cross basic blocks are always transferred 16 // between basic blocks in vreg_1 virtual registers and are lowered by this 17 // pass. 18 // 19 // The only instructions that use or define vreg_1 virtual registers are COPY, 20 // PHI, and IMPLICIT_DEF. 21 // 22 //===----------------------------------------------------------------------===// 23 24 #include "AMDGPU.h" 25 #include "AMDGPUSubtarget.h" 26 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 27 #include "SIInstrInfo.h" 28 #include "llvm/CodeGen/MachineDominators.h" 29 #include "llvm/CodeGen/MachineFunctionPass.h" 30 #include "llvm/CodeGen/MachineInstrBuilder.h" 31 #include "llvm/CodeGen/MachinePostDominators.h" 32 #include "llvm/CodeGen/MachineRegisterInfo.h" 33 #include "llvm/CodeGen/MachineSSAUpdater.h" 34 #include "llvm/IR/Function.h" 35 #include "llvm/IR/LLVMContext.h" 36 #include "llvm/InitializePasses.h" 37 #include "llvm/Support/Debug.h" 38 #include "llvm/Target/TargetMachine.h" 39 40 #define DEBUG_TYPE "si-i1-copies" 41 42 using namespace llvm; 43 44 static unsigned createLaneMaskReg(MachineFunction &MF); 45 static unsigned insertUndefLaneMask(MachineBasicBlock &MBB); 46 47 namespace { 48 49 class SILowerI1Copies : public MachineFunctionPass { 50 public: 51 static char ID; 52 53 private: 54 bool IsWave32 = false; 55 MachineFunction *MF = nullptr; 56 MachineDominatorTree *DT = nullptr; 57 MachinePostDominatorTree *PDT = nullptr; 58 MachineRegisterInfo *MRI = nullptr; 59 const GCNSubtarget *ST = nullptr; 60 const SIInstrInfo *TII = nullptr; 61 62 unsigned ExecReg; 63 unsigned MovOp; 64 unsigned AndOp; 65 unsigned OrOp; 66 unsigned XorOp; 67 unsigned AndN2Op; 68 unsigned OrN2Op; 69 70 DenseSet<unsigned> ConstrainRegs; 71 72 public: 73 SILowerI1Copies() : MachineFunctionPass(ID) { 74 initializeSILowerI1CopiesPass(*PassRegistry::getPassRegistry()); 75 } 76 77 bool runOnMachineFunction(MachineFunction &MF) override; 78 79 StringRef getPassName() const override { return "SI Lower i1 Copies"; } 80 81 void getAnalysisUsage(AnalysisUsage &AU) const override { 82 AU.setPreservesCFG(); 83 AU.addRequired<MachineDominatorTree>(); 84 AU.addRequired<MachinePostDominatorTree>(); 85 MachineFunctionPass::getAnalysisUsage(AU); 86 } 87 88 private: 89 void lowerCopiesFromI1(); 90 void lowerPhis(); 91 void lowerCopiesToI1(); 92 bool isConstantLaneMask(Register Reg, bool &Val) const; 93 void buildMergeLaneMasks(MachineBasicBlock &MBB, 94 MachineBasicBlock::iterator I, const DebugLoc &DL, 95 unsigned DstReg, unsigned PrevReg, unsigned CurReg); 96 MachineBasicBlock::iterator 97 getSaluInsertionAtEnd(MachineBasicBlock &MBB) const; 98 99 bool isVreg1(Register Reg) const { 100 return Reg.isVirtual() && MRI->getRegClass(Reg) == &AMDGPU::VReg_1RegClass; 101 } 102 103 bool isLaneMaskReg(unsigned Reg) const { 104 return TII->getRegisterInfo().isSGPRReg(*MRI, Reg) && 105 TII->getRegisterInfo().getRegSizeInBits(Reg, *MRI) == 106 ST->getWavefrontSize(); 107 } 108 }; 109 110 /// Helper class that determines the relationship between incoming values of a 111 /// phi in the control flow graph to determine where an incoming value can 112 /// simply be taken as a scalar lane mask as-is, and where it needs to be 113 /// merged with another, previously defined lane mask. 114 /// 115 /// The approach is as follows: 116 /// - Determine all basic blocks which, starting from the incoming blocks, 117 /// a wave may reach before entering the def block (the block containing the 118 /// phi). 119 /// - If an incoming block has no predecessors in this set, we can take the 120 /// incoming value as a scalar lane mask as-is. 121 /// -- A special case of this is when the def block has a self-loop. 122 /// - Otherwise, the incoming value needs to be merged with a previously 123 /// defined lane mask. 124 /// - If there is a path into the set of reachable blocks that does _not_ go 125 /// through an incoming block where we can take the scalar lane mask as-is, 126 /// we need to invent an available value for the SSAUpdater. Choices are 127 /// 0 and undef, with differing consequences for how to merge values etc. 128 /// 129 /// TODO: We could use region analysis to quickly skip over SESE regions during 130 /// the traversal. 131 /// 132 class PhiIncomingAnalysis { 133 MachinePostDominatorTree &PDT; 134 135 // For each reachable basic block, whether it is a source in the induced 136 // subgraph of the CFG. 137 DenseMap<MachineBasicBlock *, bool> ReachableMap; 138 SmallVector<MachineBasicBlock *, 4> ReachableOrdered; 139 SmallVector<MachineBasicBlock *, 4> Stack; 140 SmallVector<MachineBasicBlock *, 4> Predecessors; 141 142 public: 143 PhiIncomingAnalysis(MachinePostDominatorTree &PDT) : PDT(PDT) {} 144 145 /// Returns whether \p MBB is a source in the induced subgraph of reachable 146 /// blocks. 147 bool isSource(MachineBasicBlock &MBB) const { 148 return ReachableMap.find(&MBB)->second; 149 } 150 151 ArrayRef<MachineBasicBlock *> predecessors() const { return Predecessors; } 152 153 void analyze(MachineBasicBlock &DefBlock, 154 ArrayRef<MachineBasicBlock *> IncomingBlocks) { 155 assert(Stack.empty()); 156 ReachableMap.clear(); 157 ReachableOrdered.clear(); 158 Predecessors.clear(); 159 160 // Insert the def block first, so that it acts as an end point for the 161 // traversal. 162 ReachableMap.try_emplace(&DefBlock, false); 163 ReachableOrdered.push_back(&DefBlock); 164 165 for (MachineBasicBlock *MBB : IncomingBlocks) { 166 if (MBB == &DefBlock) { 167 ReachableMap[&DefBlock] = true; // self-loop on DefBlock 168 continue; 169 } 170 171 ReachableMap.try_emplace(MBB, false); 172 ReachableOrdered.push_back(MBB); 173 174 // If this block has a divergent terminator and the def block is its 175 // post-dominator, the wave may first visit the other successors. 176 bool Divergent = false; 177 for (MachineInstr &MI : MBB->terminators()) { 178 if (MI.getOpcode() == AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO || 179 MI.getOpcode() == AMDGPU::SI_IF || 180 MI.getOpcode() == AMDGPU::SI_ELSE || 181 MI.getOpcode() == AMDGPU::SI_LOOP) { 182 Divergent = true; 183 break; 184 } 185 } 186 187 if (Divergent && PDT.dominates(&DefBlock, MBB)) { 188 for (MachineBasicBlock *Succ : MBB->successors()) 189 Stack.push_back(Succ); 190 } 191 } 192 193 while (!Stack.empty()) { 194 MachineBasicBlock *MBB = Stack.pop_back_val(); 195 if (!ReachableMap.try_emplace(MBB, false).second) 196 continue; 197 ReachableOrdered.push_back(MBB); 198 199 for (MachineBasicBlock *Succ : MBB->successors()) 200 Stack.push_back(Succ); 201 } 202 203 for (MachineBasicBlock *MBB : ReachableOrdered) { 204 bool HaveReachablePred = false; 205 for (MachineBasicBlock *Pred : MBB->predecessors()) { 206 if (ReachableMap.count(Pred)) { 207 HaveReachablePred = true; 208 } else { 209 Stack.push_back(Pred); 210 } 211 } 212 if (!HaveReachablePred) 213 ReachableMap[MBB] = true; 214 if (HaveReachablePred) { 215 for (MachineBasicBlock *UnreachablePred : Stack) { 216 if (llvm::find(Predecessors, UnreachablePred) == Predecessors.end()) 217 Predecessors.push_back(UnreachablePred); 218 } 219 } 220 Stack.clear(); 221 } 222 } 223 }; 224 225 /// Helper class that detects loops which require us to lower an i1 COPY into 226 /// bitwise manipulation. 227 /// 228 /// Unfortunately, we cannot use LoopInfo because LoopInfo does not distinguish 229 /// between loops with the same header. Consider this example: 230 /// 231 /// A-+-+ 232 /// | | | 233 /// B-+ | 234 /// | | 235 /// C---+ 236 /// 237 /// A is the header of a loop containing A, B, and C as far as LoopInfo is 238 /// concerned. However, an i1 COPY in B that is used in C must be lowered to 239 /// bitwise operations to combine results from different loop iterations when 240 /// B has a divergent branch (since by default we will compile this code such 241 /// that threads in a wave are merged at the entry of C). 242 /// 243 /// The following rule is implemented to determine whether bitwise operations 244 /// are required: use the bitwise lowering for a def in block B if a backward 245 /// edge to B is reachable without going through the nearest common 246 /// post-dominator of B and all uses of the def. 247 /// 248 /// TODO: This rule is conservative because it does not check whether the 249 /// relevant branches are actually divergent. 250 /// 251 /// The class is designed to cache the CFG traversal so that it can be re-used 252 /// for multiple defs within the same basic block. 253 /// 254 /// TODO: We could use region analysis to quickly skip over SESE regions during 255 /// the traversal. 256 /// 257 class LoopFinder { 258 MachineDominatorTree &DT; 259 MachinePostDominatorTree &PDT; 260 261 // All visited / reachable block, tagged by level (level 0 is the def block, 262 // level 1 are all blocks reachable including but not going through the def 263 // block's IPDOM, etc.). 264 DenseMap<MachineBasicBlock *, unsigned> Visited; 265 266 // Nearest common dominator of all visited blocks by level (level 0 is the 267 // def block). Used for seeding the SSAUpdater. 268 SmallVector<MachineBasicBlock *, 4> CommonDominators; 269 270 // Post-dominator of all visited blocks. 271 MachineBasicBlock *VisitedPostDom = nullptr; 272 273 // Level at which a loop was found: 0 is not possible; 1 = a backward edge is 274 // reachable without going through the IPDOM of the def block (if the IPDOM 275 // itself has an edge to the def block, the loop level is 2), etc. 276 unsigned FoundLoopLevel = ~0u; 277 278 MachineBasicBlock *DefBlock = nullptr; 279 SmallVector<MachineBasicBlock *, 4> Stack; 280 SmallVector<MachineBasicBlock *, 4> NextLevel; 281 282 public: 283 LoopFinder(MachineDominatorTree &DT, MachinePostDominatorTree &PDT) 284 : DT(DT), PDT(PDT) {} 285 286 void initialize(MachineBasicBlock &MBB) { 287 Visited.clear(); 288 CommonDominators.clear(); 289 Stack.clear(); 290 NextLevel.clear(); 291 VisitedPostDom = nullptr; 292 FoundLoopLevel = ~0u; 293 294 DefBlock = &MBB; 295 } 296 297 /// Check whether a backward edge can be reached without going through the 298 /// given \p PostDom of the def block. 299 /// 300 /// Return the level of \p PostDom if a loop was found, or 0 otherwise. 301 unsigned findLoop(MachineBasicBlock *PostDom) { 302 MachineDomTreeNode *PDNode = PDT.getNode(DefBlock); 303 304 if (!VisitedPostDom) 305 advanceLevel(); 306 307 unsigned Level = 0; 308 while (PDNode->getBlock() != PostDom) { 309 if (PDNode->getBlock() == VisitedPostDom) 310 advanceLevel(); 311 PDNode = PDNode->getIDom(); 312 Level++; 313 if (FoundLoopLevel == Level) 314 return Level; 315 } 316 317 return 0; 318 } 319 320 /// Add undef values dominating the loop and the optionally given additional 321 /// blocks, so that the SSA updater doesn't have to search all the way to the 322 /// function entry. 323 void addLoopEntries(unsigned LoopLevel, MachineSSAUpdater &SSAUpdater, 324 ArrayRef<MachineBasicBlock *> Blocks = {}) { 325 assert(LoopLevel < CommonDominators.size()); 326 327 MachineBasicBlock *Dom = CommonDominators[LoopLevel]; 328 for (MachineBasicBlock *MBB : Blocks) 329 Dom = DT.findNearestCommonDominator(Dom, MBB); 330 331 if (!inLoopLevel(*Dom, LoopLevel, Blocks)) { 332 SSAUpdater.AddAvailableValue(Dom, insertUndefLaneMask(*Dom)); 333 } else { 334 // The dominator is part of the loop or the given blocks, so add the 335 // undef value to unreachable predecessors instead. 336 for (MachineBasicBlock *Pred : Dom->predecessors()) { 337 if (!inLoopLevel(*Pred, LoopLevel, Blocks)) 338 SSAUpdater.AddAvailableValue(Pred, insertUndefLaneMask(*Pred)); 339 } 340 } 341 } 342 343 private: 344 bool inLoopLevel(MachineBasicBlock &MBB, unsigned LoopLevel, 345 ArrayRef<MachineBasicBlock *> Blocks) const { 346 auto DomIt = Visited.find(&MBB); 347 if (DomIt != Visited.end() && DomIt->second <= LoopLevel) 348 return true; 349 350 if (llvm::find(Blocks, &MBB) != Blocks.end()) 351 return true; 352 353 return false; 354 } 355 356 void advanceLevel() { 357 MachineBasicBlock *VisitedDom; 358 359 if (!VisitedPostDom) { 360 VisitedPostDom = DefBlock; 361 VisitedDom = DefBlock; 362 Stack.push_back(DefBlock); 363 } else { 364 VisitedPostDom = PDT.getNode(VisitedPostDom)->getIDom()->getBlock(); 365 VisitedDom = CommonDominators.back(); 366 367 for (unsigned i = 0; i < NextLevel.size();) { 368 if (PDT.dominates(VisitedPostDom, NextLevel[i])) { 369 Stack.push_back(NextLevel[i]); 370 371 NextLevel[i] = NextLevel.back(); 372 NextLevel.pop_back(); 373 } else { 374 i++; 375 } 376 } 377 } 378 379 unsigned Level = CommonDominators.size(); 380 while (!Stack.empty()) { 381 MachineBasicBlock *MBB = Stack.pop_back_val(); 382 if (!PDT.dominates(VisitedPostDom, MBB)) 383 NextLevel.push_back(MBB); 384 385 Visited[MBB] = Level; 386 VisitedDom = DT.findNearestCommonDominator(VisitedDom, MBB); 387 388 for (MachineBasicBlock *Succ : MBB->successors()) { 389 if (Succ == DefBlock) { 390 if (MBB == VisitedPostDom) 391 FoundLoopLevel = std::min(FoundLoopLevel, Level + 1); 392 else 393 FoundLoopLevel = std::min(FoundLoopLevel, Level); 394 continue; 395 } 396 397 if (Visited.try_emplace(Succ, ~0u).second) { 398 if (MBB == VisitedPostDom) 399 NextLevel.push_back(Succ); 400 else 401 Stack.push_back(Succ); 402 } 403 } 404 } 405 406 CommonDominators.push_back(VisitedDom); 407 } 408 }; 409 410 } // End anonymous namespace. 411 412 INITIALIZE_PASS_BEGIN(SILowerI1Copies, DEBUG_TYPE, "SI Lower i1 Copies", false, 413 false) 414 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 415 INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree) 416 INITIALIZE_PASS_END(SILowerI1Copies, DEBUG_TYPE, "SI Lower i1 Copies", false, 417 false) 418 419 char SILowerI1Copies::ID = 0; 420 421 char &llvm::SILowerI1CopiesID = SILowerI1Copies::ID; 422 423 FunctionPass *llvm::createSILowerI1CopiesPass() { 424 return new SILowerI1Copies(); 425 } 426 427 static unsigned createLaneMaskReg(MachineFunction &MF) { 428 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 429 MachineRegisterInfo &MRI = MF.getRegInfo(); 430 return MRI.createVirtualRegister(ST.isWave32() ? &AMDGPU::SReg_32RegClass 431 : &AMDGPU::SReg_64RegClass); 432 } 433 434 static unsigned insertUndefLaneMask(MachineBasicBlock &MBB) { 435 MachineFunction &MF = *MBB.getParent(); 436 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 437 const SIInstrInfo *TII = ST.getInstrInfo(); 438 unsigned UndefReg = createLaneMaskReg(MF); 439 BuildMI(MBB, MBB.getFirstTerminator(), {}, TII->get(AMDGPU::IMPLICIT_DEF), 440 UndefReg); 441 return UndefReg; 442 } 443 444 /// Lower all instructions that def or use vreg_1 registers. 445 /// 446 /// In a first pass, we lower COPYs from vreg_1 to vector registers, as can 447 /// occur around inline assembly. We do this first, before vreg_1 registers 448 /// are changed to scalar mask registers. 449 /// 450 /// Then we lower all defs of vreg_1 registers. Phi nodes are lowered before 451 /// all others, because phi lowering looks through copies and can therefore 452 /// often make copy lowering unnecessary. 453 bool SILowerI1Copies::runOnMachineFunction(MachineFunction &TheMF) { 454 // Only need to run this in SelectionDAG path. 455 if (TheMF.getProperties().hasProperty( 456 MachineFunctionProperties::Property::Selected)) 457 return false; 458 459 MF = &TheMF; 460 MRI = &MF->getRegInfo(); 461 DT = &getAnalysis<MachineDominatorTree>(); 462 PDT = &getAnalysis<MachinePostDominatorTree>(); 463 464 ST = &MF->getSubtarget<GCNSubtarget>(); 465 TII = ST->getInstrInfo(); 466 IsWave32 = ST->isWave32(); 467 468 if (IsWave32) { 469 ExecReg = AMDGPU::EXEC_LO; 470 MovOp = AMDGPU::S_MOV_B32; 471 AndOp = AMDGPU::S_AND_B32; 472 OrOp = AMDGPU::S_OR_B32; 473 XorOp = AMDGPU::S_XOR_B32; 474 AndN2Op = AMDGPU::S_ANDN2_B32; 475 OrN2Op = AMDGPU::S_ORN2_B32; 476 } else { 477 ExecReg = AMDGPU::EXEC; 478 MovOp = AMDGPU::S_MOV_B64; 479 AndOp = AMDGPU::S_AND_B64; 480 OrOp = AMDGPU::S_OR_B64; 481 XorOp = AMDGPU::S_XOR_B64; 482 AndN2Op = AMDGPU::S_ANDN2_B64; 483 OrN2Op = AMDGPU::S_ORN2_B64; 484 } 485 486 lowerCopiesFromI1(); 487 lowerPhis(); 488 lowerCopiesToI1(); 489 490 for (unsigned Reg : ConstrainRegs) 491 MRI->constrainRegClass(Reg, &AMDGPU::SReg_1_XEXECRegClass); 492 ConstrainRegs.clear(); 493 494 return true; 495 } 496 497 #ifndef NDEBUG 498 static bool isVRegCompatibleReg(const SIRegisterInfo &TRI, 499 const MachineRegisterInfo &MRI, 500 Register Reg) { 501 unsigned Size = TRI.getRegSizeInBits(Reg, MRI); 502 return Size == 1 || Size == 32; 503 } 504 #endif 505 506 void SILowerI1Copies::lowerCopiesFromI1() { 507 SmallVector<MachineInstr *, 4> DeadCopies; 508 509 for (MachineBasicBlock &MBB : *MF) { 510 for (MachineInstr &MI : MBB) { 511 if (MI.getOpcode() != AMDGPU::COPY) 512 continue; 513 514 Register DstReg = MI.getOperand(0).getReg(); 515 Register SrcReg = MI.getOperand(1).getReg(); 516 if (!isVreg1(SrcReg)) 517 continue; 518 519 if (isLaneMaskReg(DstReg) || isVreg1(DstReg)) 520 continue; 521 522 // Copy into a 32-bit vector register. 523 LLVM_DEBUG(dbgs() << "Lower copy from i1: " << MI); 524 DebugLoc DL = MI.getDebugLoc(); 525 526 assert(isVRegCompatibleReg(TII->getRegisterInfo(), *MRI, DstReg)); 527 assert(!MI.getOperand(0).getSubReg()); 528 529 ConstrainRegs.insert(SrcReg); 530 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 531 .addImm(0) 532 .addImm(0) 533 .addImm(0) 534 .addImm(-1) 535 .addReg(SrcReg); 536 DeadCopies.push_back(&MI); 537 } 538 539 for (MachineInstr *MI : DeadCopies) 540 MI->eraseFromParent(); 541 DeadCopies.clear(); 542 } 543 } 544 545 void SILowerI1Copies::lowerPhis() { 546 MachineSSAUpdater SSAUpdater(*MF); 547 LoopFinder LF(*DT, *PDT); 548 PhiIncomingAnalysis PIA(*PDT); 549 SmallVector<MachineInstr *, 4> Vreg1Phis; 550 SmallVector<MachineBasicBlock *, 4> IncomingBlocks; 551 SmallVector<unsigned, 4> IncomingRegs; 552 SmallVector<unsigned, 4> IncomingUpdated; 553 #ifndef NDEBUG 554 DenseSet<unsigned> PhiRegisters; 555 #endif 556 557 for (MachineBasicBlock &MBB : *MF) { 558 for (MachineInstr &MI : MBB.phis()) { 559 if (isVreg1(MI.getOperand(0).getReg())) 560 Vreg1Phis.push_back(&MI); 561 } 562 } 563 564 MachineBasicBlock *PrevMBB = nullptr; 565 for (MachineInstr *MI : Vreg1Phis) { 566 MachineBasicBlock &MBB = *MI->getParent(); 567 if (&MBB != PrevMBB) { 568 LF.initialize(MBB); 569 PrevMBB = &MBB; 570 } 571 572 LLVM_DEBUG(dbgs() << "Lower PHI: " << *MI); 573 574 Register DstReg = MI->getOperand(0).getReg(); 575 MRI->setRegClass(DstReg, IsWave32 ? &AMDGPU::SReg_32RegClass 576 : &AMDGPU::SReg_64RegClass); 577 578 // Collect incoming values. 579 for (unsigned i = 1; i < MI->getNumOperands(); i += 2) { 580 assert(i + 1 < MI->getNumOperands()); 581 Register IncomingReg = MI->getOperand(i).getReg(); 582 MachineBasicBlock *IncomingMBB = MI->getOperand(i + 1).getMBB(); 583 MachineInstr *IncomingDef = MRI->getUniqueVRegDef(IncomingReg); 584 585 if (IncomingDef->getOpcode() == AMDGPU::COPY) { 586 IncomingReg = IncomingDef->getOperand(1).getReg(); 587 assert(isLaneMaskReg(IncomingReg) || isVreg1(IncomingReg)); 588 assert(!IncomingDef->getOperand(1).getSubReg()); 589 } else if (IncomingDef->getOpcode() == AMDGPU::IMPLICIT_DEF) { 590 continue; 591 } else { 592 assert(IncomingDef->isPHI() || PhiRegisters.count(IncomingReg)); 593 } 594 595 IncomingBlocks.push_back(IncomingMBB); 596 IncomingRegs.push_back(IncomingReg); 597 } 598 599 #ifndef NDEBUG 600 PhiRegisters.insert(DstReg); 601 #endif 602 603 // Phis in a loop that are observed outside the loop receive a simple but 604 // conservatively correct treatment. 605 std::vector<MachineBasicBlock *> DomBlocks = {&MBB}; 606 for (MachineInstr &Use : MRI->use_instructions(DstReg)) 607 DomBlocks.push_back(Use.getParent()); 608 609 MachineBasicBlock *PostDomBound = 610 PDT->findNearestCommonDominator(DomBlocks); 611 unsigned FoundLoopLevel = LF.findLoop(PostDomBound); 612 613 SSAUpdater.Initialize(DstReg); 614 615 if (FoundLoopLevel) { 616 LF.addLoopEntries(FoundLoopLevel, SSAUpdater, IncomingBlocks); 617 618 for (unsigned i = 0; i < IncomingRegs.size(); ++i) { 619 IncomingUpdated.push_back(createLaneMaskReg(*MF)); 620 SSAUpdater.AddAvailableValue(IncomingBlocks[i], 621 IncomingUpdated.back()); 622 } 623 624 for (unsigned i = 0; i < IncomingRegs.size(); ++i) { 625 MachineBasicBlock &IMBB = *IncomingBlocks[i]; 626 buildMergeLaneMasks( 627 IMBB, getSaluInsertionAtEnd(IMBB), {}, IncomingUpdated[i], 628 SSAUpdater.GetValueInMiddleOfBlock(&IMBB), IncomingRegs[i]); 629 } 630 } else { 631 // The phi is not observed from outside a loop. Use a more accurate 632 // lowering. 633 PIA.analyze(MBB, IncomingBlocks); 634 635 for (MachineBasicBlock *MBB : PIA.predecessors()) 636 SSAUpdater.AddAvailableValue(MBB, insertUndefLaneMask(*MBB)); 637 638 for (unsigned i = 0; i < IncomingRegs.size(); ++i) { 639 MachineBasicBlock &IMBB = *IncomingBlocks[i]; 640 if (PIA.isSource(IMBB)) { 641 IncomingUpdated.push_back(0); 642 SSAUpdater.AddAvailableValue(&IMBB, IncomingRegs[i]); 643 } else { 644 IncomingUpdated.push_back(createLaneMaskReg(*MF)); 645 SSAUpdater.AddAvailableValue(&IMBB, IncomingUpdated.back()); 646 } 647 } 648 649 for (unsigned i = 0; i < IncomingRegs.size(); ++i) { 650 if (!IncomingUpdated[i]) 651 continue; 652 653 MachineBasicBlock &IMBB = *IncomingBlocks[i]; 654 buildMergeLaneMasks( 655 IMBB, getSaluInsertionAtEnd(IMBB), {}, IncomingUpdated[i], 656 SSAUpdater.GetValueInMiddleOfBlock(&IMBB), IncomingRegs[i]); 657 } 658 } 659 660 Register NewReg = SSAUpdater.GetValueInMiddleOfBlock(&MBB); 661 if (NewReg != DstReg) { 662 MRI->replaceRegWith(NewReg, DstReg); 663 MI->eraseFromParent(); 664 } 665 666 IncomingBlocks.clear(); 667 IncomingRegs.clear(); 668 IncomingUpdated.clear(); 669 } 670 } 671 672 void SILowerI1Copies::lowerCopiesToI1() { 673 MachineSSAUpdater SSAUpdater(*MF); 674 LoopFinder LF(*DT, *PDT); 675 SmallVector<MachineInstr *, 4> DeadCopies; 676 677 for (MachineBasicBlock &MBB : *MF) { 678 LF.initialize(MBB); 679 680 for (MachineInstr &MI : MBB) { 681 if (MI.getOpcode() != AMDGPU::IMPLICIT_DEF && 682 MI.getOpcode() != AMDGPU::COPY) 683 continue; 684 685 Register DstReg = MI.getOperand(0).getReg(); 686 if (!isVreg1(DstReg)) 687 continue; 688 689 if (MRI->use_empty(DstReg)) { 690 DeadCopies.push_back(&MI); 691 continue; 692 } 693 694 LLVM_DEBUG(dbgs() << "Lower Other: " << MI); 695 696 MRI->setRegClass(DstReg, IsWave32 ? &AMDGPU::SReg_32RegClass 697 : &AMDGPU::SReg_64RegClass); 698 if (MI.getOpcode() == AMDGPU::IMPLICIT_DEF) 699 continue; 700 701 DebugLoc DL = MI.getDebugLoc(); 702 Register SrcReg = MI.getOperand(1).getReg(); 703 assert(!MI.getOperand(1).getSubReg()); 704 705 if (!SrcReg.isVirtual() || (!isLaneMaskReg(SrcReg) && !isVreg1(SrcReg))) { 706 assert(TII->getRegisterInfo().getRegSizeInBits(SrcReg, *MRI) == 32); 707 unsigned TmpReg = createLaneMaskReg(*MF); 708 BuildMI(MBB, MI, DL, TII->get(AMDGPU::V_CMP_NE_U32_e64), TmpReg) 709 .addReg(SrcReg) 710 .addImm(0); 711 MI.getOperand(1).setReg(TmpReg); 712 SrcReg = TmpReg; 713 } 714 715 // Defs in a loop that are observed outside the loop must be transformed 716 // into appropriate bit manipulation. 717 std::vector<MachineBasicBlock *> DomBlocks = {&MBB}; 718 for (MachineInstr &Use : MRI->use_instructions(DstReg)) 719 DomBlocks.push_back(Use.getParent()); 720 721 MachineBasicBlock *PostDomBound = 722 PDT->findNearestCommonDominator(DomBlocks); 723 unsigned FoundLoopLevel = LF.findLoop(PostDomBound); 724 if (FoundLoopLevel) { 725 SSAUpdater.Initialize(DstReg); 726 SSAUpdater.AddAvailableValue(&MBB, DstReg); 727 LF.addLoopEntries(FoundLoopLevel, SSAUpdater); 728 729 buildMergeLaneMasks(MBB, MI, DL, DstReg, 730 SSAUpdater.GetValueInMiddleOfBlock(&MBB), SrcReg); 731 DeadCopies.push_back(&MI); 732 } 733 } 734 735 for (MachineInstr *MI : DeadCopies) 736 MI->eraseFromParent(); 737 DeadCopies.clear(); 738 } 739 } 740 741 bool SILowerI1Copies::isConstantLaneMask(Register Reg, bool &Val) const { 742 const MachineInstr *MI; 743 for (;;) { 744 MI = MRI->getUniqueVRegDef(Reg); 745 if (MI->getOpcode() != AMDGPU::COPY) 746 break; 747 748 Reg = MI->getOperand(1).getReg(); 749 if (!Reg.isVirtual()) 750 return false; 751 if (!isLaneMaskReg(Reg)) 752 return false; 753 } 754 755 if (MI->getOpcode() != MovOp) 756 return false; 757 758 if (!MI->getOperand(1).isImm()) 759 return false; 760 761 int64_t Imm = MI->getOperand(1).getImm(); 762 if (Imm == 0) { 763 Val = false; 764 return true; 765 } 766 if (Imm == -1) { 767 Val = true; 768 return true; 769 } 770 771 return false; 772 } 773 774 static void instrDefsUsesSCC(const MachineInstr &MI, bool &Def, bool &Use) { 775 Def = false; 776 Use = false; 777 778 for (const MachineOperand &MO : MI.operands()) { 779 if (MO.isReg() && MO.getReg() == AMDGPU::SCC) { 780 if (MO.isUse()) 781 Use = true; 782 else 783 Def = true; 784 } 785 } 786 } 787 788 /// Return a point at the end of the given \p MBB to insert SALU instructions 789 /// for lane mask calculation. Take terminators and SCC into account. 790 MachineBasicBlock::iterator 791 SILowerI1Copies::getSaluInsertionAtEnd(MachineBasicBlock &MBB) const { 792 auto InsertionPt = MBB.getFirstTerminator(); 793 bool TerminatorsUseSCC = false; 794 for (auto I = InsertionPt, E = MBB.end(); I != E; ++I) { 795 bool DefsSCC; 796 instrDefsUsesSCC(*I, DefsSCC, TerminatorsUseSCC); 797 if (TerminatorsUseSCC || DefsSCC) 798 break; 799 } 800 801 if (!TerminatorsUseSCC) 802 return InsertionPt; 803 804 while (InsertionPt != MBB.begin()) { 805 InsertionPt--; 806 807 bool DefSCC, UseSCC; 808 instrDefsUsesSCC(*InsertionPt, DefSCC, UseSCC); 809 if (DefSCC) 810 return InsertionPt; 811 } 812 813 // We should have at least seen an IMPLICIT_DEF or COPY 814 llvm_unreachable("SCC used by terminator but no def in block"); 815 } 816 817 void SILowerI1Copies::buildMergeLaneMasks(MachineBasicBlock &MBB, 818 MachineBasicBlock::iterator I, 819 const DebugLoc &DL, unsigned DstReg, 820 unsigned PrevReg, unsigned CurReg) { 821 bool PrevVal; 822 bool PrevConstant = isConstantLaneMask(PrevReg, PrevVal); 823 bool CurVal; 824 bool CurConstant = isConstantLaneMask(CurReg, CurVal); 825 826 if (PrevConstant && CurConstant) { 827 if (PrevVal == CurVal) { 828 BuildMI(MBB, I, DL, TII->get(AMDGPU::COPY), DstReg).addReg(CurReg); 829 } else if (CurVal) { 830 BuildMI(MBB, I, DL, TII->get(AMDGPU::COPY), DstReg).addReg(ExecReg); 831 } else { 832 BuildMI(MBB, I, DL, TII->get(XorOp), DstReg) 833 .addReg(ExecReg) 834 .addImm(-1); 835 } 836 return; 837 } 838 839 unsigned PrevMaskedReg = 0; 840 unsigned CurMaskedReg = 0; 841 if (!PrevConstant) { 842 if (CurConstant && CurVal) { 843 PrevMaskedReg = PrevReg; 844 } else { 845 PrevMaskedReg = createLaneMaskReg(*MF); 846 BuildMI(MBB, I, DL, TII->get(AndN2Op), PrevMaskedReg) 847 .addReg(PrevReg) 848 .addReg(ExecReg); 849 } 850 } 851 if (!CurConstant) { 852 // TODO: check whether CurReg is already masked by EXEC 853 if (PrevConstant && PrevVal) { 854 CurMaskedReg = CurReg; 855 } else { 856 CurMaskedReg = createLaneMaskReg(*MF); 857 BuildMI(MBB, I, DL, TII->get(AndOp), CurMaskedReg) 858 .addReg(CurReg) 859 .addReg(ExecReg); 860 } 861 } 862 863 if (PrevConstant && !PrevVal) { 864 BuildMI(MBB, I, DL, TII->get(AMDGPU::COPY), DstReg) 865 .addReg(CurMaskedReg); 866 } else if (CurConstant && !CurVal) { 867 BuildMI(MBB, I, DL, TII->get(AMDGPU::COPY), DstReg) 868 .addReg(PrevMaskedReg); 869 } else if (PrevConstant && PrevVal) { 870 BuildMI(MBB, I, DL, TII->get(OrN2Op), DstReg) 871 .addReg(CurMaskedReg) 872 .addReg(ExecReg); 873 } else { 874 BuildMI(MBB, I, DL, TII->get(OrOp), DstReg) 875 .addReg(PrevMaskedReg) 876 .addReg(CurMaskedReg ? CurMaskedReg : ExecReg); 877 } 878 } 879