18bcb0991SDimitry Andric //=- MachineLoopUtils.cpp - Functions for manipulating loops ----------------=// 28bcb0991SDimitry Andric // 38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bcb0991SDimitry Andric // 78bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 88bcb0991SDimitry Andric 9480093f4SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 108bcb0991SDimitry Andric #include "llvm/CodeGen/MachineLoopUtils.h" 118bcb0991SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 128bcb0991SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 138bcb0991SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 148bcb0991SDimitry Andric using namespace llvm; 158bcb0991SDimitry Andric 168bcb0991SDimitry Andric namespace { 178bcb0991SDimitry Andric // MI's parent and BB are clones of each other. Find the equivalent copy of MI 188bcb0991SDimitry Andric // in BB. 198bcb0991SDimitry Andric MachineInstr &findEquivalentInstruction(MachineInstr &MI, 208bcb0991SDimitry Andric MachineBasicBlock *BB) { 218bcb0991SDimitry Andric MachineBasicBlock *PB = MI.getParent(); 228bcb0991SDimitry Andric unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI)); 238bcb0991SDimitry Andric return *std::next(BB->instr_begin(), Offset); 248bcb0991SDimitry Andric } 258bcb0991SDimitry Andric } // namespace 268bcb0991SDimitry Andric 278bcb0991SDimitry Andric MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction, 288bcb0991SDimitry Andric MachineBasicBlock *Loop, 298bcb0991SDimitry Andric MachineRegisterInfo &MRI, 308bcb0991SDimitry Andric const TargetInstrInfo *TII) { 318bcb0991SDimitry Andric MachineFunction &MF = *Loop->getParent(); 328bcb0991SDimitry Andric MachineBasicBlock *Preheader = *Loop->pred_begin(); 338bcb0991SDimitry Andric if (Preheader == Loop) 348bcb0991SDimitry Andric Preheader = *std::next(Loop->pred_begin()); 358bcb0991SDimitry Andric MachineBasicBlock *Exit = *Loop->succ_begin(); 368bcb0991SDimitry Andric if (Exit == Loop) 378bcb0991SDimitry Andric Exit = *std::next(Loop->succ_begin()); 388bcb0991SDimitry Andric 398bcb0991SDimitry Andric MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock()); 408bcb0991SDimitry Andric if (Direction == LPD_Front) 418bcb0991SDimitry Andric MF.insert(Loop->getIterator(), NewBB); 428bcb0991SDimitry Andric else 438bcb0991SDimitry Andric MF.insert(std::next(Loop->getIterator()), NewBB); 448bcb0991SDimitry Andric 45*5ffd83dbSDimitry Andric DenseMap<Register, Register> Remaps; 468bcb0991SDimitry Andric auto InsertPt = NewBB->end(); 478bcb0991SDimitry Andric for (MachineInstr &MI : *Loop) { 488bcb0991SDimitry Andric MachineInstr *NewMI = MF.CloneMachineInstr(&MI); 498bcb0991SDimitry Andric NewBB->insert(InsertPt, NewMI); 508bcb0991SDimitry Andric for (MachineOperand &MO : NewMI->defs()) { 518bcb0991SDimitry Andric Register OrigR = MO.getReg(); 528bcb0991SDimitry Andric if (OrigR.isPhysical()) 538bcb0991SDimitry Andric continue; 548bcb0991SDimitry Andric Register &R = Remaps[OrigR]; 558bcb0991SDimitry Andric R = MRI.createVirtualRegister(MRI.getRegClass(OrigR)); 568bcb0991SDimitry Andric MO.setReg(R); 578bcb0991SDimitry Andric 588bcb0991SDimitry Andric if (Direction == LPD_Back) { 598bcb0991SDimitry Andric // Replace all uses outside the original loop with the new register. 608bcb0991SDimitry Andric // FIXME: is the use_iterator stable enough to mutate register uses 618bcb0991SDimitry Andric // while iterating? 628bcb0991SDimitry Andric SmallVector<MachineOperand *, 4> Uses; 638bcb0991SDimitry Andric for (auto &Use : MRI.use_operands(OrigR)) 648bcb0991SDimitry Andric if (Use.getParent()->getParent() != Loop) 658bcb0991SDimitry Andric Uses.push_back(&Use); 668bcb0991SDimitry Andric for (auto *Use : Uses) { 678bcb0991SDimitry Andric MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg())); 688bcb0991SDimitry Andric Use->setReg(R); 698bcb0991SDimitry Andric } 708bcb0991SDimitry Andric } 718bcb0991SDimitry Andric } 728bcb0991SDimitry Andric } 738bcb0991SDimitry Andric 748bcb0991SDimitry Andric for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I) 758bcb0991SDimitry Andric for (MachineOperand &MO : I->uses()) 768bcb0991SDimitry Andric if (MO.isReg() && Remaps.count(MO.getReg())) 778bcb0991SDimitry Andric MO.setReg(Remaps[MO.getReg()]); 788bcb0991SDimitry Andric 798bcb0991SDimitry Andric for (auto I = NewBB->begin(); I->isPHI(); ++I) { 808bcb0991SDimitry Andric MachineInstr &MI = *I; 818bcb0991SDimitry Andric unsigned LoopRegIdx = 3, InitRegIdx = 1; 828bcb0991SDimitry Andric if (MI.getOperand(2).getMBB() != Preheader) 838bcb0991SDimitry Andric std::swap(LoopRegIdx, InitRegIdx); 848bcb0991SDimitry Andric MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop); 858bcb0991SDimitry Andric assert(OrigPhi.isPHI()); 868bcb0991SDimitry Andric if (Direction == LPD_Front) { 878bcb0991SDimitry Andric // When peeling front, we are only left with the initial value from the 888bcb0991SDimitry Andric // preheader. 898bcb0991SDimitry Andric Register R = MI.getOperand(LoopRegIdx).getReg(); 908bcb0991SDimitry Andric if (Remaps.count(R)) 918bcb0991SDimitry Andric R = Remaps[R]; 928bcb0991SDimitry Andric OrigPhi.getOperand(InitRegIdx).setReg(R); 938bcb0991SDimitry Andric MI.RemoveOperand(LoopRegIdx + 1); 948bcb0991SDimitry Andric MI.RemoveOperand(LoopRegIdx + 0); 958bcb0991SDimitry Andric } else { 968bcb0991SDimitry Andric // When peeling back, the initial value is the loop-carried value from 978bcb0991SDimitry Andric // the original loop. 988bcb0991SDimitry Andric Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg(); 998bcb0991SDimitry Andric MI.getOperand(LoopRegIdx).setReg(LoopReg); 1008bcb0991SDimitry Andric MI.RemoveOperand(InitRegIdx + 1); 1018bcb0991SDimitry Andric MI.RemoveOperand(InitRegIdx + 0); 1028bcb0991SDimitry Andric } 1038bcb0991SDimitry Andric } 1048bcb0991SDimitry Andric 1058bcb0991SDimitry Andric DebugLoc DL; 1068bcb0991SDimitry Andric if (Direction == LPD_Front) { 1078bcb0991SDimitry Andric Preheader->replaceSuccessor(Loop, NewBB); 1088bcb0991SDimitry Andric NewBB->addSuccessor(Loop); 1098bcb0991SDimitry Andric Loop->replacePhiUsesWith(Preheader, NewBB); 1108bcb0991SDimitry Andric if (TII->removeBranch(*Preheader) > 0) 1118bcb0991SDimitry Andric TII->insertBranch(*Preheader, NewBB, nullptr, {}, DL); 1128bcb0991SDimitry Andric TII->removeBranch(*NewBB); 1138bcb0991SDimitry Andric TII->insertBranch(*NewBB, Loop, nullptr, {}, DL); 1148bcb0991SDimitry Andric } else { 1158bcb0991SDimitry Andric Loop->replaceSuccessor(Exit, NewBB); 1168bcb0991SDimitry Andric Exit->replacePhiUsesWith(Loop, NewBB); 1178bcb0991SDimitry Andric NewBB->addSuccessor(Exit); 1188bcb0991SDimitry Andric 1198bcb0991SDimitry Andric MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 1208bcb0991SDimitry Andric SmallVector<MachineOperand, 4> Cond; 1218bcb0991SDimitry Andric bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond); 1228bcb0991SDimitry Andric (void)CanAnalyzeBr; 1238bcb0991SDimitry Andric assert(CanAnalyzeBr && "Must be able to analyze the loop branch!"); 1248bcb0991SDimitry Andric TII->removeBranch(*Loop); 1258bcb0991SDimitry Andric TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB, 1268bcb0991SDimitry Andric FBB == Exit ? NewBB : FBB, Cond, DL); 1278bcb0991SDimitry Andric if (TII->removeBranch(*NewBB) > 0) 1288bcb0991SDimitry Andric TII->insertBranch(*NewBB, Exit, nullptr, {}, DL); 1298bcb0991SDimitry Andric } 1308bcb0991SDimitry Andric 1318bcb0991SDimitry Andric return NewBB; 1328bcb0991SDimitry Andric } 133480093f4SDimitry Andric 134480093f4SDimitry Andric bool llvm::isRegLiveInExitBlocks(MachineLoop *Loop, int PhysReg) { 135480093f4SDimitry Andric SmallVector<MachineBasicBlock *, 4> ExitBlocks; 136480093f4SDimitry Andric Loop->getExitBlocks(ExitBlocks); 137480093f4SDimitry Andric 138480093f4SDimitry Andric for (auto *MBB : ExitBlocks) 139480093f4SDimitry Andric if (MBB->isLiveIn(PhysReg)) 140480093f4SDimitry Andric return true; 141480093f4SDimitry Andric 142480093f4SDimitry Andric return false; 143480093f4SDimitry Andric } 144