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