1*9026518eSJames Molloy //=- MachineLoopUtils.cpp - Functions for manipulating loops ----------------=// 2*9026518eSJames Molloy // 3*9026518eSJames Molloy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*9026518eSJames Molloy // See https://llvm.org/LICENSE.txt for license information. 5*9026518eSJames Molloy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*9026518eSJames Molloy // 7*9026518eSJames Molloy //===----------------------------------------------------------------------===// 8*9026518eSJames Molloy 9*9026518eSJames Molloy #include "llvm/CodeGen/MachineLoopUtils.h" 10*9026518eSJames Molloy #include "llvm/CodeGen/MachineBasicBlock.h" 11*9026518eSJames Molloy #include "llvm/CodeGen/MachineRegisterInfo.h" 12*9026518eSJames Molloy #include "llvm/CodeGen/TargetInstrInfo.h" 13*9026518eSJames Molloy using namespace llvm; 14*9026518eSJames Molloy 15*9026518eSJames Molloy namespace { 16*9026518eSJames Molloy // MI's parent and BB are clones of each other. Find the equivalent copy of MI 17*9026518eSJames Molloy // in BB. 18*9026518eSJames Molloy MachineInstr &findEquivalentInstruction(MachineInstr &MI, 19*9026518eSJames Molloy MachineBasicBlock *BB) { 20*9026518eSJames Molloy MachineBasicBlock *PB = MI.getParent(); 21*9026518eSJames Molloy unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI)); 22*9026518eSJames Molloy return *std::next(BB->instr_begin(), Offset); 23*9026518eSJames Molloy } 24*9026518eSJames Molloy } // namespace 25*9026518eSJames Molloy 26*9026518eSJames Molloy MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction, 27*9026518eSJames Molloy MachineBasicBlock *Loop, 28*9026518eSJames Molloy MachineRegisterInfo &MRI, 29*9026518eSJames Molloy const TargetInstrInfo *TII) { 30*9026518eSJames Molloy MachineFunction &MF = *Loop->getParent(); 31*9026518eSJames Molloy MachineBasicBlock *Preheader = *Loop->pred_begin(); 32*9026518eSJames Molloy if (Preheader == Loop) 33*9026518eSJames Molloy Preheader = *std::next(Loop->pred_begin()); 34*9026518eSJames Molloy MachineBasicBlock *Exit = *Loop->succ_begin(); 35*9026518eSJames Molloy if (Exit == Loop) 36*9026518eSJames Molloy Exit = *std::next(Loop->succ_begin()); 37*9026518eSJames Molloy 38*9026518eSJames Molloy MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock()); 39*9026518eSJames Molloy if (Direction == LPD_Front) 40*9026518eSJames Molloy MF.insert(Loop->getIterator(), NewBB); 41*9026518eSJames Molloy else 42*9026518eSJames Molloy MF.insert(std::next(Loop->getIterator()), NewBB); 43*9026518eSJames Molloy 44*9026518eSJames Molloy // FIXME: Add DenseMapInfo trait for Register so we can use it as a key. 45*9026518eSJames Molloy DenseMap<unsigned, Register> Remaps; 46*9026518eSJames Molloy auto InsertPt = NewBB->end(); 47*9026518eSJames Molloy for (MachineInstr &MI : *Loop) { 48*9026518eSJames Molloy MachineInstr *NewMI = MF.CloneMachineInstr(&MI); 49*9026518eSJames Molloy NewBB->insert(InsertPt, NewMI); 50*9026518eSJames Molloy for (MachineOperand &MO : NewMI->defs()) { 51*9026518eSJames Molloy Register OrigR = MO.getReg(); 52*9026518eSJames Molloy if (OrigR.isPhysical()) 53*9026518eSJames Molloy continue; 54*9026518eSJames Molloy Register &R = Remaps[OrigR]; 55*9026518eSJames Molloy R = MRI.createVirtualRegister(MRI.getRegClass(OrigR)); 56*9026518eSJames Molloy MO.setReg(R); 57*9026518eSJames Molloy 58*9026518eSJames Molloy if (Direction == LPD_Back) { 59*9026518eSJames Molloy // Replace all uses outside the original loop with the new register. 60*9026518eSJames Molloy // FIXME: is the use_iterator stable enough to mutate register uses 61*9026518eSJames Molloy // while iterating? 62*9026518eSJames Molloy SmallVector<MachineOperand *, 4> Uses; 63*9026518eSJames Molloy for (auto &Use : MRI.use_operands(OrigR)) 64*9026518eSJames Molloy if (Use.getParent()->getParent() != Loop) 65*9026518eSJames Molloy Uses.push_back(&Use); 66*9026518eSJames Molloy for (auto *Use : Uses) { 67*9026518eSJames Molloy MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg())); 68*9026518eSJames Molloy Use->setReg(R); 69*9026518eSJames Molloy } 70*9026518eSJames Molloy } 71*9026518eSJames Molloy } 72*9026518eSJames Molloy } 73*9026518eSJames Molloy 74*9026518eSJames Molloy for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I) 75*9026518eSJames Molloy for (MachineOperand &MO : I->uses()) 76*9026518eSJames Molloy if (MO.isReg() && Remaps.count(MO.getReg())) 77*9026518eSJames Molloy MO.setReg(Remaps[MO.getReg()]); 78*9026518eSJames Molloy 79*9026518eSJames Molloy for (auto I = NewBB->begin(); I->isPHI(); ++I) { 80*9026518eSJames Molloy MachineInstr &MI = *I; 81*9026518eSJames Molloy unsigned LoopRegIdx = 3, InitRegIdx = 1; 82*9026518eSJames Molloy if (MI.getOperand(2).getMBB() != Preheader) 83*9026518eSJames Molloy std::swap(LoopRegIdx, InitRegIdx); 84*9026518eSJames Molloy MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop); 85*9026518eSJames Molloy assert(OrigPhi.isPHI()); 86*9026518eSJames Molloy if (Direction == LPD_Front) { 87*9026518eSJames Molloy // When peeling front, we are only left with the initial value from the 88*9026518eSJames Molloy // preheader. 89*9026518eSJames Molloy Register R = MI.getOperand(LoopRegIdx).getReg(); 90*9026518eSJames Molloy if (Remaps.count(R)) 91*9026518eSJames Molloy R = Remaps[R]; 92*9026518eSJames Molloy OrigPhi.getOperand(InitRegIdx).setReg(R); 93*9026518eSJames Molloy MI.RemoveOperand(LoopRegIdx + 1); 94*9026518eSJames Molloy MI.RemoveOperand(LoopRegIdx + 0); 95*9026518eSJames Molloy } else { 96*9026518eSJames Molloy // When peeling back, the initial value is the loop-carried value from 97*9026518eSJames Molloy // the original loop. 98*9026518eSJames Molloy Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg(); 99*9026518eSJames Molloy MI.getOperand(LoopRegIdx).setReg(LoopReg); 100*9026518eSJames Molloy MI.RemoveOperand(InitRegIdx + 1); 101*9026518eSJames Molloy MI.RemoveOperand(InitRegIdx + 0); 102*9026518eSJames Molloy } 103*9026518eSJames Molloy } 104*9026518eSJames Molloy 105*9026518eSJames Molloy DebugLoc DL; 106*9026518eSJames Molloy if (Direction == LPD_Front) { 107*9026518eSJames Molloy Preheader->replaceSuccessor(Loop, NewBB); 108*9026518eSJames Molloy NewBB->addSuccessor(Loop); 109*9026518eSJames Molloy Loop->replacePhiUsesWith(Preheader, NewBB); 110*9026518eSJames Molloy if (TII->removeBranch(*Preheader) > 0) 111*9026518eSJames Molloy TII->insertBranch(*Preheader, NewBB, nullptr, {}, DL); 112*9026518eSJames Molloy TII->removeBranch(*NewBB); 113*9026518eSJames Molloy TII->insertBranch(*NewBB, Loop, nullptr, {}, DL); 114*9026518eSJames Molloy } else { 115*9026518eSJames Molloy Loop->replaceSuccessor(Exit, NewBB); 116*9026518eSJames Molloy Exit->replacePhiUsesWith(Loop, NewBB); 117*9026518eSJames Molloy NewBB->addSuccessor(Exit); 118*9026518eSJames Molloy 119*9026518eSJames Molloy MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 120*9026518eSJames Molloy SmallVector<MachineOperand, 4> Cond; 121*9026518eSJames Molloy bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond); 122*9026518eSJames Molloy (void)CanAnalyzeBr; 123*9026518eSJames Molloy assert(CanAnalyzeBr && "Must be able to analyze the loop branch!"); 124*9026518eSJames Molloy TII->removeBranch(*Loop); 125*9026518eSJames Molloy TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB, 126*9026518eSJames Molloy FBB == Exit ? NewBB : FBB, Cond, DL); 127*9026518eSJames Molloy if (TII->removeBranch(*NewBB) > 0) 128*9026518eSJames Molloy TII->insertBranch(*NewBB, Exit, nullptr, {}, DL); 129*9026518eSJames Molloy } 130*9026518eSJames Molloy 131*9026518eSJames Molloy return NewBB; 132*9026518eSJames Molloy } 133