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.
findEquivalentInstruction(MachineInstr & MI,MachineBasicBlock * 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 
PeelSingleBlockLoop(LoopPeelDirection Direction,MachineBasicBlock * Loop,MachineRegisterInfo & MRI,const TargetInstrInfo * TII)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 
455ffd83dbSDimitry 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 }
133