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
99026518eSJames Molloy #include "llvm/CodeGen/MachineLoopUtils.h"
109026518eSJames Molloy #include "llvm/CodeGen/MachineBasicBlock.h"
119026518eSJames Molloy #include "llvm/CodeGen/MachineRegisterInfo.h"
129026518eSJames Molloy #include "llvm/CodeGen/TargetInstrInfo.h"
139026518eSJames Molloy using namespace llvm;
149026518eSJames Molloy
159026518eSJames Molloy namespace {
169026518eSJames Molloy // MI's parent and BB are clones of each other. Find the equivalent copy of MI
179026518eSJames Molloy // in BB.
findEquivalentInstruction(MachineInstr & MI,MachineBasicBlock * BB)189026518eSJames Molloy MachineInstr &findEquivalentInstruction(MachineInstr &MI,
199026518eSJames Molloy MachineBasicBlock *BB) {
209026518eSJames Molloy MachineBasicBlock *PB = MI.getParent();
219026518eSJames Molloy unsigned Offset = std::distance(PB->instr_begin(), MachineBasicBlock::instr_iterator(MI));
229026518eSJames Molloy return *std::next(BB->instr_begin(), Offset);
239026518eSJames Molloy }
249026518eSJames Molloy } // namespace
259026518eSJames Molloy
PeelSingleBlockLoop(LoopPeelDirection Direction,MachineBasicBlock * Loop,MachineRegisterInfo & MRI,const TargetInstrInfo * TII)269026518eSJames Molloy MachineBasicBlock *llvm::PeelSingleBlockLoop(LoopPeelDirection Direction,
279026518eSJames Molloy MachineBasicBlock *Loop,
289026518eSJames Molloy MachineRegisterInfo &MRI,
299026518eSJames Molloy const TargetInstrInfo *TII) {
309026518eSJames Molloy MachineFunction &MF = *Loop->getParent();
319026518eSJames Molloy MachineBasicBlock *Preheader = *Loop->pred_begin();
329026518eSJames Molloy if (Preheader == Loop)
339026518eSJames Molloy Preheader = *std::next(Loop->pred_begin());
349026518eSJames Molloy MachineBasicBlock *Exit = *Loop->succ_begin();
359026518eSJames Molloy if (Exit == Loop)
369026518eSJames Molloy Exit = *std::next(Loop->succ_begin());
379026518eSJames Molloy
389026518eSJames Molloy MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(Loop->getBasicBlock());
399026518eSJames Molloy if (Direction == LPD_Front)
409026518eSJames Molloy MF.insert(Loop->getIterator(), NewBB);
419026518eSJames Molloy else
429026518eSJames Molloy MF.insert(std::next(Loop->getIterator()), NewBB);
439026518eSJames Molloy
44bf730e16SJay Foad DenseMap<Register, Register> Remaps;
459026518eSJames Molloy auto InsertPt = NewBB->end();
469026518eSJames Molloy for (MachineInstr &MI : *Loop) {
479026518eSJames Molloy MachineInstr *NewMI = MF.CloneMachineInstr(&MI);
489026518eSJames Molloy NewBB->insert(InsertPt, NewMI);
499026518eSJames Molloy for (MachineOperand &MO : NewMI->defs()) {
509026518eSJames Molloy Register OrigR = MO.getReg();
519026518eSJames Molloy if (OrigR.isPhysical())
529026518eSJames Molloy continue;
539026518eSJames Molloy Register &R = Remaps[OrigR];
549026518eSJames Molloy R = MRI.createVirtualRegister(MRI.getRegClass(OrigR));
559026518eSJames Molloy MO.setReg(R);
569026518eSJames Molloy
579026518eSJames Molloy if (Direction == LPD_Back) {
589026518eSJames Molloy // Replace all uses outside the original loop with the new register.
599026518eSJames Molloy // FIXME: is the use_iterator stable enough to mutate register uses
609026518eSJames Molloy // while iterating?
619026518eSJames Molloy SmallVector<MachineOperand *, 4> Uses;
629026518eSJames Molloy for (auto &Use : MRI.use_operands(OrigR))
639026518eSJames Molloy if (Use.getParent()->getParent() != Loop)
649026518eSJames Molloy Uses.push_back(&Use);
659026518eSJames Molloy for (auto *Use : Uses) {
66e995e344SDavid Green const TargetRegisterClass *ConstrainRegClass =
679026518eSJames Molloy MRI.constrainRegClass(R, MRI.getRegClass(Use->getReg()));
68e995e344SDavid Green assert(ConstrainRegClass &&
69e995e344SDavid Green "Expected a valid constrained register class!");
70*44582afeSHaojian Wu (void)ConstrainRegClass;
719026518eSJames Molloy Use->setReg(R);
729026518eSJames Molloy }
739026518eSJames Molloy }
749026518eSJames Molloy }
759026518eSJames Molloy }
769026518eSJames Molloy
779026518eSJames Molloy for (auto I = NewBB->getFirstNonPHI(); I != NewBB->end(); ++I)
789026518eSJames Molloy for (MachineOperand &MO : I->uses())
799026518eSJames Molloy if (MO.isReg() && Remaps.count(MO.getReg()))
809026518eSJames Molloy MO.setReg(Remaps[MO.getReg()]);
819026518eSJames Molloy
829026518eSJames Molloy for (auto I = NewBB->begin(); I->isPHI(); ++I) {
839026518eSJames Molloy MachineInstr &MI = *I;
849026518eSJames Molloy unsigned LoopRegIdx = 3, InitRegIdx = 1;
859026518eSJames Molloy if (MI.getOperand(2).getMBB() != Preheader)
869026518eSJames Molloy std::swap(LoopRegIdx, InitRegIdx);
879026518eSJames Molloy MachineInstr &OrigPhi = findEquivalentInstruction(MI, Loop);
889026518eSJames Molloy assert(OrigPhi.isPHI());
899026518eSJames Molloy if (Direction == LPD_Front) {
909026518eSJames Molloy // When peeling front, we are only left with the initial value from the
919026518eSJames Molloy // preheader.
929026518eSJames Molloy Register R = MI.getOperand(LoopRegIdx).getReg();
939026518eSJames Molloy if (Remaps.count(R))
949026518eSJames Molloy R = Remaps[R];
959026518eSJames Molloy OrigPhi.getOperand(InitRegIdx).setReg(R);
9637b37838SShengchen Kan MI.removeOperand(LoopRegIdx + 1);
9737b37838SShengchen Kan MI.removeOperand(LoopRegIdx + 0);
989026518eSJames Molloy } else {
999026518eSJames Molloy // When peeling back, the initial value is the loop-carried value from
1009026518eSJames Molloy // the original loop.
1019026518eSJames Molloy Register LoopReg = OrigPhi.getOperand(LoopRegIdx).getReg();
1029026518eSJames Molloy MI.getOperand(LoopRegIdx).setReg(LoopReg);
10337b37838SShengchen Kan MI.removeOperand(InitRegIdx + 1);
10437b37838SShengchen Kan MI.removeOperand(InitRegIdx + 0);
1059026518eSJames Molloy }
1069026518eSJames Molloy }
1079026518eSJames Molloy
1089026518eSJames Molloy DebugLoc DL;
1099026518eSJames Molloy if (Direction == LPD_Front) {
110a43d2573SHendrik Greving Preheader->ReplaceUsesOfBlockWith(Loop, NewBB);
1119026518eSJames Molloy NewBB->addSuccessor(Loop);
1129026518eSJames Molloy Loop->replacePhiUsesWith(Preheader, NewBB);
113a43d2573SHendrik Greving Preheader->updateTerminator(Loop);
1149026518eSJames Molloy TII->removeBranch(*NewBB);
1159026518eSJames Molloy TII->insertBranch(*NewBB, Loop, nullptr, {}, DL);
1169026518eSJames Molloy } else {
1179026518eSJames Molloy Loop->replaceSuccessor(Exit, NewBB);
1189026518eSJames Molloy Exit->replacePhiUsesWith(Loop, NewBB);
1199026518eSJames Molloy NewBB->addSuccessor(Exit);
1209026518eSJames Molloy
1219026518eSJames Molloy MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
1229026518eSJames Molloy SmallVector<MachineOperand, 4> Cond;
1239026518eSJames Molloy bool CanAnalyzeBr = !TII->analyzeBranch(*Loop, TBB, FBB, Cond);
1249026518eSJames Molloy (void)CanAnalyzeBr;
1259026518eSJames Molloy assert(CanAnalyzeBr && "Must be able to analyze the loop branch!");
1269026518eSJames Molloy TII->removeBranch(*Loop);
1279026518eSJames Molloy TII->insertBranch(*Loop, TBB == Exit ? NewBB : TBB,
1289026518eSJames Molloy FBB == Exit ? NewBB : FBB, Cond, DL);
1299026518eSJames Molloy if (TII->removeBranch(*NewBB) > 0)
1309026518eSJames Molloy TII->insertBranch(*NewBB, Exit, nullptr, {}, DL);
1319026518eSJames Molloy }
1329026518eSJames Molloy
1339026518eSJames Molloy return NewBB;
1349026518eSJames Molloy }
135