1fd719d18SJakob Stoklund Olesen //===-- ExpandPostRAPseudos.cpp - Pseudo instruction expansion pass -------===//
2f152df1eSJakob Stoklund Olesen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f152df1eSJakob Stoklund Olesen //
7f152df1eSJakob Stoklund Olesen //===----------------------------------------------------------------------===//
8f152df1eSJakob Stoklund Olesen //
9fd719d18SJakob Stoklund Olesen // This file defines a pass that expands COPY and SUBREG_TO_REG pseudo
10fd719d18SJakob Stoklund Olesen // instructions after register allocation.
11f152df1eSJakob Stoklund Olesen //
12f152df1eSJakob Stoklund Olesen //===----------------------------------------------------------------------===//
13f152df1eSJakob Stoklund Olesen 
14f152df1eSJakob Stoklund Olesen #include "llvm/CodeGen/MachineFunctionPass.h"
15f152df1eSJakob Stoklund Olesen #include "llvm/CodeGen/MachineInstr.h"
166bda14b3SChandler Carruth #include "llvm/CodeGen/Passes.h"
173f833edcSDavid Blaikie #include "llvm/CodeGen/TargetInstrInfo.h"
18b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
19b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetSubtargetInfo.h"
2005da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
21f152df1eSJakob Stoklund Olesen #include "llvm/Support/Debug.h"
22f152df1eSJakob Stoklund Olesen #include "llvm/Support/raw_ostream.h"
23d913448bSEric Christopher 
24f152df1eSJakob Stoklund Olesen using namespace llvm;
25f152df1eSJakob Stoklund Olesen 
261b9dde08SChandler Carruth #define DEBUG_TYPE "postrapseudos"
271b9dde08SChandler Carruth 
28f152df1eSJakob Stoklund Olesen namespace {
29fd719d18SJakob Stoklund Olesen struct ExpandPostRA : public MachineFunctionPass {
30f152df1eSJakob Stoklund Olesen private:
31f152df1eSJakob Stoklund Olesen   const TargetRegisterInfo *TRI;
32f152df1eSJakob Stoklund Olesen   const TargetInstrInfo *TII;
33f152df1eSJakob Stoklund Olesen 
34f152df1eSJakob Stoklund Olesen public:
35f152df1eSJakob Stoklund Olesen   static char ID; // Pass identification, replacement for typeid
ExpandPostRA__anon48e27c000111::ExpandPostRA36fd719d18SJakob Stoklund Olesen   ExpandPostRA() : MachineFunctionPass(ID) {}
37f152df1eSJakob Stoklund Olesen 
getAnalysisUsage__anon48e27c000111::ExpandPostRA384584cd54SCraig Topper   void getAnalysisUsage(AnalysisUsage &AU) const override {
39f152df1eSJakob Stoklund Olesen     AU.setPreservesCFG();
40f152df1eSJakob Stoklund Olesen     AU.addPreservedID(MachineLoopInfoID);
41f152df1eSJakob Stoklund Olesen     AU.addPreservedID(MachineDominatorsID);
42f152df1eSJakob Stoklund Olesen     MachineFunctionPass::getAnalysisUsage(AU);
43f152df1eSJakob Stoklund Olesen   }
44f152df1eSJakob Stoklund Olesen 
45f152df1eSJakob Stoklund Olesen   /// runOnMachineFunction - pass entry point
464584cd54SCraig Topper   bool runOnMachineFunction(MachineFunction&) override;
47f152df1eSJakob Stoklund Olesen 
48f152df1eSJakob Stoklund Olesen private:
49f152df1eSJakob Stoklund Olesen   bool LowerSubregToReg(MachineInstr *MI);
50f152df1eSJakob Stoklund Olesen   bool LowerCopy(MachineInstr *MI);
51f152df1eSJakob Stoklund Olesen 
52be2e3f5cSMichael Kuperstein   void TransferImplicitOperands(MachineInstr *MI);
53f152df1eSJakob Stoklund Olesen };
54fd719d18SJakob Stoklund Olesen } // end anonymous namespace
55f152df1eSJakob Stoklund Olesen 
56fd719d18SJakob Stoklund Olesen char ExpandPostRA::ID = 0;
571fa5bcbeSAndrew Trick char &llvm::ExpandPostRAPseudosID = ExpandPostRA::ID;
58f152df1eSJakob Stoklund Olesen 
591527baabSMatthias Braun INITIALIZE_PASS(ExpandPostRA, DEBUG_TYPE,
601fa5bcbeSAndrew Trick                 "Post-RA pseudo instruction expansion pass", false, false)
61f152df1eSJakob Stoklund Olesen 
62be2e3f5cSMichael Kuperstein /// TransferImplicitOperands - MI is a pseudo-instruction, and the lowered
63be2e3f5cSMichael Kuperstein /// replacement instructions immediately precede it.  Copy any implicit
64f152df1eSJakob Stoklund Olesen /// operands from MI to the replacement instruction.
TransferImplicitOperands(MachineInstr * MI)65be2e3f5cSMichael Kuperstein void ExpandPostRA::TransferImplicitOperands(MachineInstr *MI) {
66f152df1eSJakob Stoklund Olesen   MachineBasicBlock::iterator CopyMI = MI;
67f152df1eSJakob Stoklund Olesen   --CopyMI;
68f152df1eSJakob Stoklund Olesen 
69984451eaSMatt Arsenault   Register DstReg = MI->getOperand(0).getReg();
70984451eaSMatt Arsenault   for (const MachineOperand &MO : MI->implicit_operands()) {
71be2e3f5cSMichael Kuperstein     CopyMI->addOperand(MO);
72984451eaSMatt Arsenault 
73984451eaSMatt Arsenault     // Be conservative about preserving kills when subregister defs are
74984451eaSMatt Arsenault     // involved. If there was implicit kill of a super-register overlapping the
75984451eaSMatt Arsenault     // copy result, we would kill the subregisters previous copies defined.
76984451eaSMatt Arsenault     if (MO.isKill() && TRI->regsOverlap(DstReg, MO.getReg()))
77984451eaSMatt Arsenault       CopyMI->getOperand(CopyMI->getNumOperands() - 1).setIsKill(false);
78984451eaSMatt Arsenault   }
79f152df1eSJakob Stoklund Olesen }
80f152df1eSJakob Stoklund Olesen 
LowerSubregToReg(MachineInstr * MI)81fd719d18SJakob Stoklund Olesen bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) {
82f152df1eSJakob Stoklund Olesen   MachineBasicBlock *MBB = MI->getParent();
83f152df1eSJakob Stoklund Olesen   assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
84f152df1eSJakob Stoklund Olesen          MI->getOperand(1).isImm() &&
85f152df1eSJakob Stoklund Olesen          (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
86f152df1eSJakob Stoklund Olesen           MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
87f152df1eSJakob Stoklund Olesen 
880c476111SDaniel Sanders   Register DstReg = MI->getOperand(0).getReg();
890c476111SDaniel Sanders   Register InsReg = MI->getOperand(2).getReg();
90f152df1eSJakob Stoklund Olesen   assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
91f152df1eSJakob Stoklund Olesen   unsigned SubIdx  = MI->getOperand(3).getImm();
92f152df1eSJakob Stoklund Olesen 
93f152df1eSJakob Stoklund Olesen   assert(SubIdx != 0 && "Invalid index for insert_subreg");
940c476111SDaniel Sanders   Register DstSubReg = TRI->getSubReg(DstReg, SubIdx);
95f152df1eSJakob Stoklund Olesen 
962bea69bfSDaniel Sanders   assert(Register::isPhysicalRegister(DstReg) &&
97f152df1eSJakob Stoklund Olesen          "Insert destination must be in a physical register");
982bea69bfSDaniel Sanders   assert(Register::isPhysicalRegister(InsReg) &&
99f152df1eSJakob Stoklund Olesen          "Inserted value must be in a physical register");
100f152df1eSJakob Stoklund Olesen 
101d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
102f152df1eSJakob Stoklund Olesen 
10343090202SLang Hames   if (MI->allDefsAreDead()) {
10443090202SLang Hames     MI->setDesc(TII->get(TargetOpcode::KILL));
105*37b37838SShengchen Kan     MI->removeOperand(3); // SubIdx
106*37b37838SShengchen Kan     MI->removeOperand(1); // Imm
107d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "subreg: replaced by: " << *MI);
10843090202SLang Hames     return true;
10943090202SLang Hames   }
11043090202SLang Hames 
111f152df1eSJakob Stoklund Olesen   if (DstSubReg == InsReg) {
112b542fa51SMatthias Braun     // No need to insert an identity copy instruction.
113f152df1eSJakob Stoklund Olesen     // Watch out for case like this:
114a8a83d15SFrancis Visoiu Mistrih     // %rax = SUBREG_TO_REG 0, killed %eax, 3
1159d7bb0cbSFrancis Visoiu Mistrih     // We must leave %rax live.
116f152df1eSJakob Stoklund Olesen     if (DstReg != InsReg) {
117f152df1eSJakob Stoklund Olesen       MI->setDesc(TII->get(TargetOpcode::KILL));
118*37b37838SShengchen Kan       MI->removeOperand(3);     // SubIdx
119*37b37838SShengchen Kan       MI->removeOperand(1);     // Imm
120d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "subreg: replace by: " << *MI);
121f152df1eSJakob Stoklund Olesen       return true;
122f152df1eSJakob Stoklund Olesen     }
123d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "subreg: eliminated!");
124f152df1eSJakob Stoklund Olesen   } else {
125f152df1eSJakob Stoklund Olesen     TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
126f152df1eSJakob Stoklund Olesen                      MI->getOperand(2).isKill());
127071890b5SLang Hames 
128bc65e8f9SJakob Stoklund Olesen     // Implicitly define DstReg for subsequent uses.
129bc65e8f9SJakob Stoklund Olesen     MachineBasicBlock::iterator CopyMI = MI;
130bc65e8f9SJakob Stoklund Olesen     --CopyMI;
131bc65e8f9SJakob Stoklund Olesen     CopyMI->addRegisterDefined(DstReg);
132d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "subreg: " << *CopyMI);
133f152df1eSJakob Stoklund Olesen   }
134f152df1eSJakob Stoklund Olesen 
135d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << '\n');
136f152df1eSJakob Stoklund Olesen   MBB->erase(MI);
137f152df1eSJakob Stoklund Olesen   return true;
138f152df1eSJakob Stoklund Olesen }
139f152df1eSJakob Stoklund Olesen 
LowerCopy(MachineInstr * MI)140fd719d18SJakob Stoklund Olesen bool ExpandPostRA::LowerCopy(MachineInstr *MI) {
14143090202SLang Hames 
14243090202SLang Hames   if (MI->allDefsAreDead()) {
143d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "dead copy: " << *MI);
14443090202SLang Hames     MI->setDesc(TII->get(TargetOpcode::KILL));
145d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "replaced by: " << *MI);
14643090202SLang Hames     return true;
14743090202SLang Hames   }
14843090202SLang Hames 
149f152df1eSJakob Stoklund Olesen   MachineOperand &DstMO = MI->getOperand(0);
150f152df1eSJakob Stoklund Olesen   MachineOperand &SrcMO = MI->getOperand(1);
151f152df1eSJakob Stoklund Olesen 
152d1ec7385SJonas Paulsson   bool IdentityCopy = (SrcMO.getReg() == DstMO.getReg());
153d1ec7385SJonas Paulsson   if (IdentityCopy || SrcMO.isUndef()) {
154d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << (IdentityCopy ? "identity copy: " : "undef copy:    ")
155d34e60caSNicola Zaghen                       << *MI);
156f152df1eSJakob Stoklund Olesen     // No need to insert an identity copy instruction, but replace with a KILL
157f152df1eSJakob Stoklund Olesen     // if liveness is changed.
15843090202SLang Hames     if (SrcMO.isUndef() || MI->getNumOperands() > 2) {
159f152df1eSJakob Stoklund Olesen       // We must make sure the super-register gets killed. Replace the
160f152df1eSJakob Stoklund Olesen       // instruction with KILL.
161f152df1eSJakob Stoklund Olesen       MI->setDesc(TII->get(TargetOpcode::KILL));
162d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "replaced by:   " << *MI);
163f152df1eSJakob Stoklund Olesen       return true;
164f152df1eSJakob Stoklund Olesen     }
165f152df1eSJakob Stoklund Olesen     // Vanilla identity copy.
166f152df1eSJakob Stoklund Olesen     MI->eraseFromParent();
167f152df1eSJakob Stoklund Olesen     return true;
168f152df1eSJakob Stoklund Olesen   }
169f152df1eSJakob Stoklund Olesen 
170d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "real copy:   " << *MI);
171f152df1eSJakob Stoklund Olesen   TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(),
172f152df1eSJakob Stoklund Olesen                    DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill());
173f152df1eSJakob Stoklund Olesen 
174f152df1eSJakob Stoklund Olesen   if (MI->getNumOperands() > 2)
175be2e3f5cSMichael Kuperstein     TransferImplicitOperands(MI);
176d34e60caSNicola Zaghen   LLVM_DEBUG({
177f152df1eSJakob Stoklund Olesen     MachineBasicBlock::iterator dMI = MI;
178f152df1eSJakob Stoklund Olesen     dbgs() << "replaced by: " << *(--dMI);
179f152df1eSJakob Stoklund Olesen   });
180f152df1eSJakob Stoklund Olesen   MI->eraseFromParent();
181f152df1eSJakob Stoklund Olesen   return true;
182f152df1eSJakob Stoklund Olesen }
183f152df1eSJakob Stoklund Olesen 
184f152df1eSJakob Stoklund Olesen /// runOnMachineFunction - Reduce subregister inserts and extracts to register
185f152df1eSJakob Stoklund Olesen /// copies.
186f152df1eSJakob Stoklund Olesen ///
runOnMachineFunction(MachineFunction & MF)187fd719d18SJakob Stoklund Olesen bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) {
188d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "Machine Function\n"
189fd719d18SJakob Stoklund Olesen                     << "********** EXPANDING POST-RA PSEUDO INSTRS **********\n"
190c8c2920aSDavid Blaikie                     << "********** Function: " << MF.getName() << '\n');
191fc6de428SEric Christopher   TRI = MF.getSubtarget().getRegisterInfo();
192fc6de428SEric Christopher   TII = MF.getSubtarget().getInstrInfo();
193f152df1eSJakob Stoklund Olesen 
194f152df1eSJakob Stoklund Olesen   bool MadeChange = false;
195f152df1eSJakob Stoklund Olesen 
196905cf88dSKazu Hirata   for (MachineBasicBlock &MBB : MF) {
1977f00806aSKazu Hirata     for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
198add0c43eSJakob Stoklund Olesen       // Only expand pseudos.
1999cfc75c2SDuncan P. N. Exon Smith       if (!MI.isPseudo())
200add0c43eSJakob Stoklund Olesen         continue;
201add0c43eSJakob Stoklund Olesen 
202add0c43eSJakob Stoklund Olesen       // Give targets a chance to expand even standard pseudos.
203add0c43eSJakob Stoklund Olesen       if (TII->expandPostRAPseudo(MI)) {
204add0c43eSJakob Stoklund Olesen         MadeChange = true;
205add0c43eSJakob Stoklund Olesen         continue;
206add0c43eSJakob Stoklund Olesen       }
207add0c43eSJakob Stoklund Olesen 
208add0c43eSJakob Stoklund Olesen       // Expand standard pseudos.
2099cfc75c2SDuncan P. N. Exon Smith       switch (MI.getOpcode()) {
210df977fedSJakob Stoklund Olesen       case TargetOpcode::SUBREG_TO_REG:
2119cfc75c2SDuncan P. N. Exon Smith         MadeChange |= LowerSubregToReg(&MI);
212df977fedSJakob Stoklund Olesen         break;
213df977fedSJakob Stoklund Olesen       case TargetOpcode::COPY:
2149cfc75c2SDuncan P. N. Exon Smith         MadeChange |= LowerCopy(&MI);
215df977fedSJakob Stoklund Olesen         break;
216df977fedSJakob Stoklund Olesen       case TargetOpcode::DBG_VALUE:
217df977fedSJakob Stoklund Olesen         continue;
218df977fedSJakob Stoklund Olesen       case TargetOpcode::INSERT_SUBREG:
219df977fedSJakob Stoklund Olesen       case TargetOpcode::EXTRACT_SUBREG:
220df977fedSJakob Stoklund Olesen         llvm_unreachable("Sub-register pseudos should have been eliminated.");
221f152df1eSJakob Stoklund Olesen       }
222f152df1eSJakob Stoklund Olesen     }
223f152df1eSJakob Stoklund Olesen   }
224f152df1eSJakob Stoklund Olesen 
225f152df1eSJakob Stoklund Olesen   return MadeChange;
226f152df1eSJakob Stoklund Olesen }
227