19026518eSJames Molloy //=- MachineLoopUtils.cpp - Functions for manipulating loops ----------------=// 29026518eSJames Molloy // 39026518eSJames Molloy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49026518eSJames Molloy // See https://llvm.org/LICENSE.txt for license information. 59026518eSJames Molloy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69026518eSJames Molloy // 79026518eSJames Molloy //===----------------------------------------------------------------------===// 89026518eSJames Molloy 9d97cf1f8SSjoerd Meijer #include "llvm/CodeGen/MachineLoopInfo.h" 109026518eSJames Molloy #include "llvm/CodeGen/MachineLoopUtils.h" 119026518eSJames Molloy #include "llvm/CodeGen/MachineBasicBlock.h" 129026518eSJames Molloy #include "llvm/CodeGen/MachineRegisterInfo.h" 139026518eSJames Molloy #include "llvm/CodeGen/TargetInstrInfo.h" 149026518eSJames Molloy using namespace llvm; 159026518eSJames Molloy 169026518eSJames Molloy namespace { 179026518eSJames Molloy // MI's parent and BB are clones of each other. Find the equivalent copy of MI 189026518eSJames Molloy // in BB. 199026518eSJames Molloy MachineInstr &findEquivalentInstruction(MachineInstr &MI, 209026518eSJames Molloy MachineBasicBlock *BB) { 219026518eSJames Molloy MachineBasicBlock *PB = MI.getParent(); 229026518eSJames Molloy unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI)); 239026518eSJames Molloy return *std::next(BB->instr_begin(), Offset); 249026518eSJames Molloy } 259026518eSJames Molloy } // namespace 269026518eSJames Molloy 279026518eSJames Molloy MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction, 289026518eSJames Molloy MachineBasicBlock *Loop, 299026518eSJames Molloy MachineRegisterInfo &MRI, 309026518eSJames Molloy const TargetInstrInfo *TII) { 319026518eSJames Molloy MachineFunction &MF = *Loop->getParent(); 329026518eSJames Molloy MachineBasicBlock *Preheader = *Loop->pred_begin(); 339026518eSJames Molloy if (Preheader == Loop) 349026518eSJames Molloy Preheader = *std::next(Loop->pred_begin()); 359026518eSJames Molloy MachineBasicBlock *Exit = *Loop->succ_begin(); 369026518eSJames Molloy if (Exit == Loop) 379026518eSJames Molloy Exit = *std::next(Loop->succ_begin()); 389026518eSJames Molloy 399026518eSJames Molloy MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock()); 409026518eSJames Molloy if (Direction == LPD_Front) 419026518eSJames Molloy MF.insert(Loop->getIterator(), NewBB); 429026518eSJames Molloy else 439026518eSJames Molloy MF.insert(std::next(Loop->getIterator()), NewBB); 449026518eSJames Molloy 45*bf730e16SJay Foad DenseMap<Register, Register> Remaps; 469026518eSJames Molloy auto InsertPt = NewBB->end(); 479026518eSJames Molloy for (MachineInstr &MI : *Loop) { 489026518eSJames Molloy MachineInstr *NewMI = MF.CloneMachineInstr(&MI); 499026518eSJames Molloy NewBB->insert(InsertPt, NewMI); 509026518eSJames Molloy for (MachineOperand &MO : NewMI->defs()) { 519026518eSJames Molloy Register OrigR = MO.getReg(); 529026518eSJames Molloy if (OrigR.isPhysical()) 539026518eSJames Molloy continue; 549026518eSJames Molloy Register &R = Remaps[OrigR]; 559026518eSJames Molloy R = MRI.createVirtualRegister(MRI.getRegClass(OrigR)); 569026518eSJames Molloy MO.setReg(R); 579026518eSJames Molloy 589026518eSJames Molloy if (Direction == LPD_Back) { 599026518eSJames Molloy // Replace all uses outside the original loop with the new register. 609026518eSJames Molloy // FIXME: is the use_iterator stable enough to mutate register uses 619026518eSJames Molloy // while iterating? 629026518eSJames Molloy SmallVector<MachineOperand *, 4> Uses; 639026518eSJames Molloy for (auto &Use : MRI.use_operands(OrigR)) 649026518eSJames Molloy if (Use.getParent()->getParent() != Loop) 659026518eSJames Molloy Uses.push_back(&Use); 669026518eSJames Molloy for (auto *Use : Uses) { 679026518eSJames Molloy MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg())); 689026518eSJames Molloy Use->setReg(R); 699026518eSJames Molloy } 709026518eSJames Molloy } 719026518eSJames Molloy } 729026518eSJames Molloy } 739026518eSJames Molloy 749026518eSJames Molloy for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I) 759026518eSJames Molloy for (MachineOperand &MO : I->uses()) 769026518eSJames Molloy if (MO.isReg() && Remaps.count(MO.getReg())) 779026518eSJames Molloy MO.setReg(Remaps[MO.getReg()]); 789026518eSJames Molloy 799026518eSJames Molloy for (auto I = NewBB->begin(); I->isPHI(); ++I) { 809026518eSJames Molloy MachineInstr &MI = *I; 819026518eSJames Molloy unsigned LoopRegIdx = 3, InitRegIdx = 1; 829026518eSJames Molloy if (MI.getOperand(2).getMBB() != Preheader) 839026518eSJames Molloy std::swap(LoopRegIdx, InitRegIdx); 849026518eSJames Molloy MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop); 859026518eSJames Molloy assert(OrigPhi.isPHI()); 869026518eSJames Molloy if (Direction == LPD_Front) { 879026518eSJames Molloy // When peeling front, we are only left with the initial value from the 889026518eSJames Molloy // preheader. 899026518eSJames Molloy Register R = MI.getOperand(LoopRegIdx).getReg(); 909026518eSJames Molloy if (Remaps.count(R)) 919026518eSJames Molloy R = Remaps[R]; 929026518eSJames Molloy OrigPhi.getOperand(InitRegIdx).setReg(R); 939026518eSJames Molloy MI.RemoveOperand(LoopRegIdx + 1); 949026518eSJames Molloy MI.RemoveOperand(LoopRegIdx + 0); 959026518eSJames Molloy } else { 969026518eSJames Molloy // When peeling back, the initial value is the loop-carried value from 979026518eSJames Molloy // the original loop. 989026518eSJames Molloy Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg(); 999026518eSJames Molloy MI.getOperand(LoopRegIdx).setReg(LoopReg); 1009026518eSJames Molloy MI.RemoveOperand(InitRegIdx + 1); 1019026518eSJames Molloy MI.RemoveOperand(InitRegIdx + 0); 1029026518eSJames Molloy } 1039026518eSJames Molloy } 1049026518eSJames Molloy 1059026518eSJames Molloy DebugLoc DL; 1069026518eSJames Molloy if (Direction == LPD_Front) { 1079026518eSJames Molloy Preheader->replaceSuccessor(Loop, NewBB); 1089026518eSJames Molloy NewBB->addSuccessor(Loop); 1099026518eSJames Molloy Loop->replacePhiUsesWith(Preheader, NewBB); 1109026518eSJames Molloy if (TII->removeBranch(*Preheader) > 0) 1119026518eSJames Molloy TII->insertBranch(*Preheader, NewBB, nullptr, {}, DL); 1129026518eSJames Molloy TII->removeBranch(*NewBB); 1139026518eSJames Molloy TII->insertBranch(*NewBB, Loop, nullptr, {}, DL); 1149026518eSJames Molloy } else { 1159026518eSJames Molloy Loop->replaceSuccessor(Exit, NewBB); 1169026518eSJames Molloy Exit->replacePhiUsesWith(Loop, NewBB); 1179026518eSJames Molloy NewBB->addSuccessor(Exit); 1189026518eSJames Molloy 1199026518eSJames Molloy MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 1209026518eSJames Molloy SmallVector<MachineOperand, 4> Cond; 1219026518eSJames Molloy bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond); 1229026518eSJames Molloy (void)CanAnalyzeBr; 1239026518eSJames Molloy assert(CanAnalyzeBr && "Must be able to analyze the loop branch!"); 1249026518eSJames Molloy TII->removeBranch(*Loop); 1259026518eSJames Molloy TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB, 1269026518eSJames Molloy FBB == Exit ? NewBB : FBB, Cond, DL); 1279026518eSJames Molloy if (TII->removeBranch(*NewBB) > 0) 1289026518eSJames Molloy TII->insertBranch(*NewBB, Exit, nullptr, {}, DL); 1299026518eSJames Molloy } 1309026518eSJames Molloy 1319026518eSJames Molloy return NewBB; 1329026518eSJames Molloy } 133d97cf1f8SSjoerd Meijer 134d97cf1f8SSjoerd Meijer bool llvm::isRegLiveInExitBlocks(MachineLoop *Loop, int PhysReg) { 135d97cf1f8SSjoerd Meijer SmallVector<MachineBasicBlock *, 4> ExitBlocks; 136d97cf1f8SSjoerd Meijer Loop->getExitBlocks(ExitBlocks); 137d97cf1f8SSjoerd Meijer 138d97cf1f8SSjoerd Meijer for (auto *MBB : ExitBlocks) 139d97cf1f8SSjoerd Meijer if (MBB->isLiveIn(PhysReg)) 140d97cf1f8SSjoerd Meijer return true; 141d97cf1f8SSjoerd Meijer 142d97cf1f8SSjoerd Meijer return false; 143d97cf1f8SSjoerd Meijer } 144