xref: /src/contrib/llvm-project/llvm/lib/CodeGen/MachineLoopUtils.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
11d5ae102SDimitry Andric //=- MachineLoopUtils.cpp - Functions for manipulating loops ----------------=//
21d5ae102SDimitry Andric //
31d5ae102SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d5ae102SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51d5ae102SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d5ae102SDimitry Andric //
71d5ae102SDimitry Andric //===----------------------------------------------------------------------===//
81d5ae102SDimitry Andric 
91d5ae102SDimitry Andric #include "llvm/CodeGen/MachineLoopUtils.h"
101d5ae102SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
111d5ae102SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
121d5ae102SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
131d5ae102SDimitry Andric using namespace llvm;
141d5ae102SDimitry Andric 
151d5ae102SDimitry Andric namespace {
161d5ae102SDimitry Andric // MI's parent and BB are clones of each other. Find the equivalent copy of MI
171d5ae102SDimitry Andric // in BB.
findEquivalentInstruction(MachineInstr & MI,MachineBasicBlock * BB)181d5ae102SDimitry Andric MachineInstr &findEquivalentInstruction(MachineInstr &MI,
191d5ae102SDimitry Andric                                         MachineBasicBlock *BB) {
201d5ae102SDimitry Andric   MachineBasicBlock *PB = MI.getParent();
211d5ae102SDimitry Andric   unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI));
221d5ae102SDimitry Andric   return *std::next(BB->instr_begin(), Offset);
231d5ae102SDimitry Andric }
241d5ae102SDimitry Andric } // namespace
251d5ae102SDimitry Andric 
PeelSingleBlockLoop(LoopPeelDirection Direction,MachineBasicBlock * Loop,MachineRegisterInfo & MRI,const TargetInstrInfo * TII)261d5ae102SDimitry Andric MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction,
271d5ae102SDimitry Andric                                              MachineBasicBlock *Loop,
281d5ae102SDimitry Andric                                              MachineRegisterInfo &MRI,
291d5ae102SDimitry Andric                                              const TargetInstrInfo *TII) {
301d5ae102SDimitry Andric   MachineFunction &MF = *Loop->getParent();
311d5ae102SDimitry Andric   MachineBasicBlock *Preheader = *Loop->pred_begin();
321d5ae102SDimitry Andric   if (Preheader == Loop)
331d5ae102SDimitry Andric     Preheader = *std::next(Loop->pred_begin());
341d5ae102SDimitry Andric   MachineBasicBlock *Exit = *Loop->succ_begin();
351d5ae102SDimitry Andric   if (Exit == Loop)
361d5ae102SDimitry Andric     Exit = *std::next(Loop->succ_begin());
371d5ae102SDimitry Andric 
381d5ae102SDimitry Andric   MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock());
391d5ae102SDimitry Andric   if (Direction == LPD_Front)
401d5ae102SDimitry Andric     MF.insert(Loop->getIterator(), NewBB);
411d5ae102SDimitry Andric   else
421d5ae102SDimitry Andric     MF.insert(std::next(Loop->getIterator()), NewBB);
431d5ae102SDimitry Andric 
44cfca06d7SDimitry Andric   DenseMap<Register, Register> Remaps;
451d5ae102SDimitry Andric   auto InsertPt = NewBB->end();
461d5ae102SDimitry Andric   for (MachineInstr &MI : *Loop) {
471d5ae102SDimitry Andric     MachineInstr *NewMI = MF.CloneMachineInstr(&MI);
481d5ae102SDimitry Andric     NewBB->insert(InsertPt, NewMI);
491d5ae102SDimitry Andric     for (MachineOperand &MO : NewMI->defs()) {
501d5ae102SDimitry Andric       Register OrigR = MO.getReg();
511d5ae102SDimitry Andric       if (OrigR.isPhysical())
521d5ae102SDimitry Andric         continue;
531d5ae102SDimitry Andric       Register &R = Remaps[OrigR];
541d5ae102SDimitry Andric       R = MRI.createVirtualRegister(MRI.getRegClass(OrigR));
551d5ae102SDimitry Andric       MO.setReg(R);
561d5ae102SDimitry Andric 
571d5ae102SDimitry Andric       if (Direction == LPD_Back) {
581d5ae102SDimitry Andric         // Replace all uses outside the original loop with the new register.
591d5ae102SDimitry Andric         // FIXME: is the use_iterator stable enough to mutate register uses
601d5ae102SDimitry Andric         // while iterating?
611d5ae102SDimitry Andric         SmallVector<MachineOperand *, 4> Uses;
621d5ae102SDimitry Andric         for (auto &Use : MRI.use_operands(OrigR))
631d5ae102SDimitry Andric           if (Use.getParent()->getParent() != Loop)
641d5ae102SDimitry Andric             Uses.push_back(&Use);
651d5ae102SDimitry Andric         for (auto *Use : Uses) {
66145449b1SDimitry Andric           const TargetRegisterClass *ConstrainRegClass =
671d5ae102SDimitry Andric               MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg()));
68145449b1SDimitry Andric           assert(ConstrainRegClass &&
69145449b1SDimitry Andric                  "Expected a valid constrained register class!");
70145449b1SDimitry Andric           (void)ConstrainRegClass;
711d5ae102SDimitry Andric           Use->setReg(R);
721d5ae102SDimitry Andric         }
731d5ae102SDimitry Andric       }
741d5ae102SDimitry Andric     }
751d5ae102SDimitry Andric   }
761d5ae102SDimitry Andric 
771d5ae102SDimitry Andric   for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I)
781d5ae102SDimitry Andric     for (MachineOperand &MO : I->uses())
791d5ae102SDimitry Andric       if (MO.isReg() && Remaps.count(MO.getReg()))
801d5ae102SDimitry Andric         MO.setReg(Remaps[MO.getReg()]);
811d5ae102SDimitry Andric 
821d5ae102SDimitry Andric   for (auto I = NewBB->begin(); I->isPHI(); ++I) {
831d5ae102SDimitry Andric     MachineInstr &MI = *I;
841d5ae102SDimitry Andric     unsigned LoopRegIdx = 3, InitRegIdx = 1;
851d5ae102SDimitry Andric     if (MI.getOperand(2).getMBB() != Preheader)
861d5ae102SDimitry Andric       std::swap(LoopRegIdx, InitRegIdx);
871d5ae102SDimitry Andric     MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop);
881d5ae102SDimitry Andric     assert(OrigPhi.isPHI());
891d5ae102SDimitry Andric     if (Direction == LPD_Front) {
901d5ae102SDimitry Andric       // When peeling front, we are only left with the initial value from the
911d5ae102SDimitry Andric       // preheader.
921d5ae102SDimitry Andric       Register R = MI.getOperand(LoopRegIdx).getReg();
931d5ae102SDimitry Andric       if (Remaps.count(R))
941d5ae102SDimitry Andric         R = Remaps[R];
951d5ae102SDimitry Andric       OrigPhi.getOperand(InitRegIdx).setReg(R);
96145449b1SDimitry Andric       MI.removeOperand(LoopRegIdx + 1);
97145449b1SDimitry Andric       MI.removeOperand(LoopRegIdx + 0);
981d5ae102SDimitry Andric     } else {
991d5ae102SDimitry Andric       // When peeling back, the initial value is the loop-carried value from
1001d5ae102SDimitry Andric       // the original loop.
1011d5ae102SDimitry Andric       Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg();
1021d5ae102SDimitry Andric       MI.getOperand(LoopRegIdx).setReg(LoopReg);
103145449b1SDimitry Andric       MI.removeOperand(InitRegIdx + 1);
104145449b1SDimitry Andric       MI.removeOperand(InitRegIdx + 0);
1051d5ae102SDimitry Andric     }
1061d5ae102SDimitry Andric   }
1071d5ae102SDimitry Andric 
1081d5ae102SDimitry Andric   DebugLoc DL;
1091d5ae102SDimitry Andric   if (Direction == LPD_Front) {
110145449b1SDimitry Andric     Preheader->ReplaceUsesOfBlockWith(Loop, NewBB);
1111d5ae102SDimitry Andric     NewBB->addSuccessor(Loop);
1121d5ae102SDimitry Andric     Loop->replacePhiUsesWith(Preheader, NewBB);
113145449b1SDimitry Andric     Preheader->updateTerminator(Loop);
1141d5ae102SDimitry Andric     TII->removeBranch(*NewBB);
1151d5ae102SDimitry Andric     TII->insertBranch(*NewBB, Loop, nullptr, {}, DL);
1161d5ae102SDimitry Andric   } else {
1171d5ae102SDimitry Andric     Loop->replaceSuccessor(Exit, NewBB);
1181d5ae102SDimitry Andric     Exit->replacePhiUsesWith(Loop, NewBB);
1191d5ae102SDimitry Andric     NewBB->addSuccessor(Exit);
1201d5ae102SDimitry Andric 
1211d5ae102SDimitry Andric     MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
1221d5ae102SDimitry Andric     SmallVector<MachineOperand, 4> Cond;
1231d5ae102SDimitry Andric     bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond);
1241d5ae102SDimitry Andric     (void)CanAnalyzeBr;
1251d5ae102SDimitry Andric     assert(CanAnalyzeBr && "Must be able to analyze the loop branch!");
1261d5ae102SDimitry Andric     TII->removeBranch(*Loop);
1271d5ae102SDimitry Andric     TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB,
1281d5ae102SDimitry Andric                       FBB == Exit ? NewBB : FBB, Cond, DL);
1291d5ae102SDimitry Andric     if (TII->removeBranch(*NewBB) > 0)
1301d5ae102SDimitry Andric       TII->insertBranch(*NewBB, Exit, nullptr, {}, DL);
1311d5ae102SDimitry Andric   }
1321d5ae102SDimitry Andric 
1331d5ae102SDimitry Andric   return NewBB;
1341d5ae102SDimitry Andric }
135