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