xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-- ExpandPostRAPseudos.cpp - Pseudo instruction expansion pass -------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines a pass that expands COPY and SUBREG_TO_REG pseudo
100b57cec5SDimitry Andric // instructions after register allocation.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
20480093f4SDimitry Andric #include "llvm/InitializePasses.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "postrapseudos"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace {
290b57cec5SDimitry Andric struct ExpandPostRA : public MachineFunctionPass {
300b57cec5SDimitry Andric private:
31*06c3fb27SDimitry Andric   const TargetRegisterInfo *TRI = nullptr;
32*06c3fb27SDimitry Andric   const TargetInstrInfo *TII = nullptr;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
ExpandPostRA__anona744dd620111::ExpandPostRA360b57cec5SDimitry Andric   ExpandPostRA() : MachineFunctionPass(ID) {}
370b57cec5SDimitry Andric 
getAnalysisUsage__anona744dd620111::ExpandPostRA380b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
390b57cec5SDimitry Andric     AU.setPreservesCFG();
400b57cec5SDimitry Andric     AU.addPreservedID(MachineLoopInfoID);
410b57cec5SDimitry Andric     AU.addPreservedID(MachineDominatorsID);
420b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   /// runOnMachineFunction - pass entry point
460b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction&) override;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric private:
490b57cec5SDimitry Andric   bool LowerSubregToReg(MachineInstr *MI);
500b57cec5SDimitry Andric };
510b57cec5SDimitry Andric } // end anonymous namespace
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric char ExpandPostRA::ID = 0;
540b57cec5SDimitry Andric char &llvm::ExpandPostRAPseudosID = ExpandPostRA::ID;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric INITIALIZE_PASS(ExpandPostRA, DEBUG_TYPE,
570b57cec5SDimitry Andric                 "Post-RA pseudo instruction expansion pass", false, false)
580b57cec5SDimitry Andric 
LowerSubregToReg(MachineInstr * MI)590b57cec5SDimitry Andric bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) {
600b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
610b57cec5SDimitry Andric   assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
620b57cec5SDimitry Andric          MI->getOperand(1).isImm() &&
630b57cec5SDimitry Andric          (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
640b57cec5SDimitry Andric           MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
650b57cec5SDimitry Andric 
668bcb0991SDimitry Andric   Register DstReg = MI->getOperand(0).getReg();
678bcb0991SDimitry Andric   Register InsReg = MI->getOperand(2).getReg();
680b57cec5SDimitry Andric   assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
690b57cec5SDimitry Andric   unsigned SubIdx  = MI->getOperand(3).getImm();
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   assert(SubIdx != 0 && "Invalid index for insert_subreg");
728bcb0991SDimitry Andric   Register DstSubReg = TRI->getSubReg(DstReg, SubIdx);
730b57cec5SDimitry Andric 
74bdd1243dSDimitry Andric   assert(DstReg.isPhysical() &&
750b57cec5SDimitry Andric          "Insert destination must be in a physical register");
76bdd1243dSDimitry Andric   assert(InsReg.isPhysical() &&
770b57cec5SDimitry Andric          "Inserted value must be in a physical register");
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   if (MI->allDefsAreDead()) {
820b57cec5SDimitry Andric     MI->setDesc(TII->get(TargetOpcode::KILL));
8381ad6265SDimitry Andric     MI->removeOperand(3); // SubIdx
8481ad6265SDimitry Andric     MI->removeOperand(1); // Imm
850b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "subreg: replaced by: " << *MI);
860b57cec5SDimitry Andric     return true;
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   if (DstSubReg == InsReg) {
900b57cec5SDimitry Andric     // No need to insert an identity copy instruction.
910b57cec5SDimitry Andric     // Watch out for case like this:
920b57cec5SDimitry Andric     // %rax = SUBREG_TO_REG 0, killed %eax, 3
930b57cec5SDimitry Andric     // We must leave %rax live.
940b57cec5SDimitry Andric     if (DstReg != InsReg) {
950b57cec5SDimitry Andric       MI->setDesc(TII->get(TargetOpcode::KILL));
9681ad6265SDimitry Andric       MI->removeOperand(3);     // SubIdx
9781ad6265SDimitry Andric       MI->removeOperand(1);     // Imm
980b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "subreg: replace by: " << *MI);
990b57cec5SDimitry Andric       return true;
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "subreg: eliminated!");
1020b57cec5SDimitry Andric   } else {
1030b57cec5SDimitry Andric     TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
1040b57cec5SDimitry Andric                      MI->getOperand(2).isKill());
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     // Implicitly define DstReg for subsequent uses.
1070b57cec5SDimitry Andric     MachineBasicBlock::iterator CopyMI = MI;
1080b57cec5SDimitry Andric     --CopyMI;
1090b57cec5SDimitry Andric     CopyMI->addRegisterDefined(DstReg);
1100b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "subreg: " << *CopyMI);
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << '\n');
1140b57cec5SDimitry Andric   MBB->erase(MI);
1150b57cec5SDimitry Andric   return true;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric /// runOnMachineFunction - Reduce subregister inserts and extracts to register
1190b57cec5SDimitry Andric /// copies.
1200b57cec5SDimitry Andric ///
runOnMachineFunction(MachineFunction & MF)1210b57cec5SDimitry Andric bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) {
1220b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Machine Function\n"
1230b57cec5SDimitry Andric                     << "********** EXPANDING POST-RA PSEUDO INSTRS **********\n"
1240b57cec5SDimitry Andric                     << "********** Function: " << MF.getName() << '\n');
1250b57cec5SDimitry Andric   TRI = MF.getSubtarget().getRegisterInfo();
1260b57cec5SDimitry Andric   TII = MF.getSubtarget().getInstrInfo();
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   bool MadeChange = false;
1290b57cec5SDimitry Andric 
130fe6060f1SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
131349cc55cSDimitry Andric     for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
1320b57cec5SDimitry Andric       // Only expand pseudos.
1330b57cec5SDimitry Andric       if (!MI.isPseudo())
1340b57cec5SDimitry Andric         continue;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric       // Give targets a chance to expand even standard pseudos.
1370b57cec5SDimitry Andric       if (TII->expandPostRAPseudo(MI)) {
1380b57cec5SDimitry Andric         MadeChange = true;
1390b57cec5SDimitry Andric         continue;
1400b57cec5SDimitry Andric       }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric       // Expand standard pseudos.
1430b57cec5SDimitry Andric       switch (MI.getOpcode()) {
1440b57cec5SDimitry Andric       case TargetOpcode::SUBREG_TO_REG:
1450b57cec5SDimitry Andric         MadeChange |= LowerSubregToReg(&MI);
1460b57cec5SDimitry Andric         break;
1470b57cec5SDimitry Andric       case TargetOpcode::COPY:
148*06c3fb27SDimitry Andric         TII->lowerCopy(&MI, TRI);
149*06c3fb27SDimitry Andric         MadeChange = true;
1500b57cec5SDimitry Andric         break;
1510b57cec5SDimitry Andric       case TargetOpcode::DBG_VALUE:
1520b57cec5SDimitry Andric         continue;
1530b57cec5SDimitry Andric       case TargetOpcode::INSERT_SUBREG:
1540b57cec5SDimitry Andric       case TargetOpcode::EXTRACT_SUBREG:
1550b57cec5SDimitry Andric         llvm_unreachable("Sub-register pseudos should have been eliminated.");
1560b57cec5SDimitry Andric       }
1570b57cec5SDimitry Andric     }
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   return MadeChange;
1610b57cec5SDimitry Andric }
162