|  | //=- MachineLoopUtils.cpp - Functions for manipulating loops ----------------=// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/CodeGen/MachineLoopUtils.h" | 
|  | #include "llvm/CodeGen/MachineBasicBlock.h" | 
|  | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | #include "llvm/CodeGen/TargetInstrInfo.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | namespace { | 
|  | // MI's parent and BB are clones of each other. Find the equivalent copy of MI | 
|  | // in BB. | 
|  | MachineInstr &findEquivalentInstruction(MachineInstr &MI, | 
|  | MachineBasicBlock *BB) { | 
|  | MachineBasicBlock *PB = MI.getParent(); | 
|  | unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI)); | 
|  | return *std::next(BB->instr_begin(), Offset); | 
|  | } | 
|  | } // namespace | 
|  |  | 
|  | MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction, | 
|  | MachineBasicBlock *Loop, | 
|  | MachineRegisterInfo &MRI, | 
|  | const TargetInstrInfo *TII) { | 
|  | MachineFunction &MF = *Loop->getParent(); | 
|  | MachineBasicBlock *Preheader = *Loop->pred_begin(); | 
|  | if (Preheader == Loop) | 
|  | Preheader = *std::next(Loop->pred_begin()); | 
|  | MachineBasicBlock *Exit = *Loop->succ_begin(); | 
|  | if (Exit == Loop) | 
|  | Exit = *std::next(Loop->succ_begin()); | 
|  |  | 
|  | MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock()); | 
|  | if (Direction == LPD_Front) | 
|  | MF.insert(Loop->getIterator(), NewBB); | 
|  | else | 
|  | MF.insert(std::next(Loop->getIterator()), NewBB); | 
|  |  | 
|  | DenseMap<Register, Register> Remaps; | 
|  | auto InsertPt = NewBB->end(); | 
|  | for (MachineInstr &MI : *Loop) { | 
|  | MachineInstr *NewMI = MF.CloneMachineInstr(&MI); | 
|  | NewBB->insert(InsertPt, NewMI); | 
|  | for (MachineOperand &MO : NewMI->defs()) { | 
|  | Register OrigR = MO.getReg(); | 
|  | if (OrigR.isPhysical()) | 
|  | continue; | 
|  | Register &R = Remaps[OrigR]; | 
|  | R = MRI.createVirtualRegister(MRI.getRegClass(OrigR)); | 
|  | MO.setReg(R); | 
|  |  | 
|  | if (Direction == LPD_Back) { | 
|  | // Replace all uses outside the original loop with the new register. | 
|  | // FIXME: is the use_iterator stable enough to mutate register uses | 
|  | // while iterating? | 
|  | SmallVector<MachineOperand *, 4> Uses; | 
|  | for (auto &Use : MRI.use_operands(OrigR)) | 
|  | if (Use.getParent()->getParent() != Loop) | 
|  | Uses.push_back(&Use); | 
|  | for (auto *Use : Uses) { | 
|  | const TargetRegisterClass *ConstrainRegClass = | 
|  | MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg())); | 
|  | assert(ConstrainRegClass && | 
|  | "Expected a valid constrained register class!"); | 
|  | (void)ConstrainRegClass; | 
|  | Use->setReg(R); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I) | 
|  | for (MachineOperand &MO : I->uses()) | 
|  | if (MO.isReg() && Remaps.count(MO.getReg())) | 
|  | MO.setReg(Remaps[MO.getReg()]); | 
|  |  | 
|  | for (auto I = NewBB->begin(); I->isPHI(); ++I) { | 
|  | MachineInstr &MI = *I; | 
|  | unsigned LoopRegIdx = 3, InitRegIdx = 1; | 
|  | if (MI.getOperand(2).getMBB() != Preheader) | 
|  | std::swap(LoopRegIdx, InitRegIdx); | 
|  | MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop); | 
|  | assert(OrigPhi.isPHI()); | 
|  | if (Direction == LPD_Front) { | 
|  | // When peeling front, we are only left with the initial value from the | 
|  | // preheader. | 
|  | Register R = MI.getOperand(LoopRegIdx).getReg(); | 
|  | if (Remaps.count(R)) | 
|  | R = Remaps[R]; | 
|  | OrigPhi.getOperand(InitRegIdx).setReg(R); | 
|  | MI.removeOperand(LoopRegIdx + 1); | 
|  | MI.removeOperand(LoopRegIdx + 0); | 
|  | } else { | 
|  | // When peeling back, the initial value is the loop-carried value from | 
|  | // the original loop. | 
|  | Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg(); | 
|  | MI.getOperand(LoopRegIdx).setReg(LoopReg); | 
|  | MI.removeOperand(InitRegIdx + 1); | 
|  | MI.removeOperand(InitRegIdx + 0); | 
|  | } | 
|  | } | 
|  |  | 
|  | DebugLoc DL; | 
|  | if (Direction == LPD_Front) { | 
|  | Preheader->ReplaceUsesOfBlockWith(Loop, NewBB); | 
|  | NewBB->addSuccessor(Loop); | 
|  | Loop->replacePhiUsesWith(Preheader, NewBB); | 
|  | Preheader->updateTerminator(Loop); | 
|  | TII->removeBranch(*NewBB); | 
|  | TII->insertBranch(*NewBB, Loop, nullptr, {}, DL); | 
|  | } else { | 
|  | Loop->replaceSuccessor(Exit, NewBB); | 
|  | Exit->replacePhiUsesWith(Loop, NewBB); | 
|  | NewBB->addSuccessor(Exit); | 
|  |  | 
|  | MachineBasicBlock *TBB = nullptr, *FBB = nullptr; | 
|  | SmallVector<MachineOperand, 4> Cond; | 
|  | bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond); | 
|  | (void)CanAnalyzeBr; | 
|  | assert(CanAnalyzeBr && "Must be able to analyze the loop branch!"); | 
|  | TII->removeBranch(*Loop); | 
|  | TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB, | 
|  | FBB == Exit ? NewBB : FBB, Cond, DL); | 
|  | if (TII->removeBranch(*NewBB) > 0) | 
|  | TII->insertBranch(*NewBB, Exit, nullptr, {}, DL); | 
|  | } | 
|  |  | 
|  | return NewBB; | 
|  | } |