xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp (revision a3c35da61bb201168575f1d18f4ca3e96937d35c)
1  //===-- ExpandPostRAPseudos.cpp - Pseudo instruction expansion pass -------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file defines a pass that expands COPY and SUBREG_TO_REG pseudo
10  // instructions after register allocation.
11  //
12  //===----------------------------------------------------------------------===//
13  
14  #include "llvm/CodeGen/MachineFunctionPass.h"
15  #include "llvm/CodeGen/MachineInstr.h"
16  #include "llvm/CodeGen/MachineInstrBuilder.h"
17  #include "llvm/CodeGen/MachineRegisterInfo.h"
18  #include "llvm/CodeGen/Passes.h"
19  #include "llvm/CodeGen/TargetInstrInfo.h"
20  #include "llvm/CodeGen/TargetRegisterInfo.h"
21  #include "llvm/CodeGen/TargetSubtargetInfo.h"
22  #include "llvm/Support/Debug.h"
23  #include "llvm/Support/raw_ostream.h"
24  
25  using namespace llvm;
26  
27  #define DEBUG_TYPE "postrapseudos"
28  
29  namespace {
30  struct ExpandPostRA : public MachineFunctionPass {
31  private:
32    const TargetRegisterInfo *TRI;
33    const TargetInstrInfo *TII;
34  
35  public:
36    static char ID; // Pass identification, replacement for typeid
37    ExpandPostRA() : MachineFunctionPass(ID) {}
38  
39    void getAnalysisUsage(AnalysisUsage &AU) const override {
40      AU.setPreservesCFG();
41      AU.addPreservedID(MachineLoopInfoID);
42      AU.addPreservedID(MachineDominatorsID);
43      MachineFunctionPass::getAnalysisUsage(AU);
44    }
45  
46    /// runOnMachineFunction - pass entry point
47    bool runOnMachineFunction(MachineFunction&) override;
48  
49  private:
50    bool LowerSubregToReg(MachineInstr *MI);
51    bool LowerCopy(MachineInstr *MI);
52  
53    void TransferImplicitOperands(MachineInstr *MI);
54  };
55  } // end anonymous namespace
56  
57  char ExpandPostRA::ID = 0;
58  char &llvm::ExpandPostRAPseudosID = ExpandPostRA::ID;
59  
60  INITIALIZE_PASS(ExpandPostRA, DEBUG_TYPE,
61                  "Post-RA pseudo instruction expansion pass", false, false)
62  
63  /// TransferImplicitOperands - MI is a pseudo-instruction, and the lowered
64  /// replacement instructions immediately precede it.  Copy any implicit
65  /// operands from MI to the replacement instruction.
66  void ExpandPostRA::TransferImplicitOperands(MachineInstr *MI) {
67    MachineBasicBlock::iterator CopyMI = MI;
68    --CopyMI;
69  
70    for (const MachineOperand &MO : MI->implicit_operands())
71      if (MO.isReg())
72        CopyMI->addOperand(MO);
73  }
74  
75  bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) {
76    MachineBasicBlock *MBB = MI->getParent();
77    assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
78           MI->getOperand(1).isImm() &&
79           (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
80            MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
81  
82    unsigned DstReg  = MI->getOperand(0).getReg();
83    unsigned InsReg  = MI->getOperand(2).getReg();
84    assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?");
85    unsigned SubIdx  = MI->getOperand(3).getImm();
86  
87    assert(SubIdx != 0 && "Invalid index for insert_subreg");
88    unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx);
89  
90    assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
91           "Insert destination must be in a physical register");
92    assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
93           "Inserted value must be in a physical register");
94  
95    LLVM_DEBUG(dbgs() << "subreg: CONVERTING: " << *MI);
96  
97    if (MI->allDefsAreDead()) {
98      MI->setDesc(TII->get(TargetOpcode::KILL));
99      MI->RemoveOperand(3); // SubIdx
100      MI->RemoveOperand(1); // Imm
101      LLVM_DEBUG(dbgs() << "subreg: replaced by: " << *MI);
102      return true;
103    }
104  
105    if (DstSubReg == InsReg) {
106      // No need to insert an identity copy instruction.
107      // Watch out for case like this:
108      // %rax = SUBREG_TO_REG 0, killed %eax, 3
109      // We must leave %rax live.
110      if (DstReg != InsReg) {
111        MI->setDesc(TII->get(TargetOpcode::KILL));
112        MI->RemoveOperand(3);     // SubIdx
113        MI->RemoveOperand(1);     // Imm
114        LLVM_DEBUG(dbgs() << "subreg: replace by: " << *MI);
115        return true;
116      }
117      LLVM_DEBUG(dbgs() << "subreg: eliminated!");
118    } else {
119      TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg,
120                       MI->getOperand(2).isKill());
121  
122      // Implicitly define DstReg for subsequent uses.
123      MachineBasicBlock::iterator CopyMI = MI;
124      --CopyMI;
125      CopyMI->addRegisterDefined(DstReg);
126      LLVM_DEBUG(dbgs() << "subreg: " << *CopyMI);
127    }
128  
129    LLVM_DEBUG(dbgs() << '\n');
130    MBB->erase(MI);
131    return true;
132  }
133  
134  bool ExpandPostRA::LowerCopy(MachineInstr *MI) {
135  
136    if (MI->allDefsAreDead()) {
137      LLVM_DEBUG(dbgs() << "dead copy: " << *MI);
138      MI->setDesc(TII->get(TargetOpcode::KILL));
139      LLVM_DEBUG(dbgs() << "replaced by: " << *MI);
140      return true;
141    }
142  
143    MachineOperand &DstMO = MI->getOperand(0);
144    MachineOperand &SrcMO = MI->getOperand(1);
145  
146    bool IdentityCopy = (SrcMO.getReg() == DstMO.getReg());
147    if (IdentityCopy || SrcMO.isUndef()) {
148      LLVM_DEBUG(dbgs() << (IdentityCopy ? "identity copy: " : "undef copy:    ")
149                        << *MI);
150      // No need to insert an identity copy instruction, but replace with a KILL
151      // if liveness is changed.
152      if (SrcMO.isUndef() || MI->getNumOperands() > 2) {
153        // We must make sure the super-register gets killed. Replace the
154        // instruction with KILL.
155        MI->setDesc(TII->get(TargetOpcode::KILL));
156        LLVM_DEBUG(dbgs() << "replaced by:   " << *MI);
157        return true;
158      }
159      // Vanilla identity copy.
160      MI->eraseFromParent();
161      return true;
162    }
163  
164    LLVM_DEBUG(dbgs() << "real copy:   " << *MI);
165    TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(),
166                     DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill());
167  
168    if (MI->getNumOperands() > 2)
169      TransferImplicitOperands(MI);
170    LLVM_DEBUG({
171      MachineBasicBlock::iterator dMI = MI;
172      dbgs() << "replaced by: " << *(--dMI);
173    });
174    MI->eraseFromParent();
175    return true;
176  }
177  
178  /// runOnMachineFunction - Reduce subregister inserts and extracts to register
179  /// copies.
180  ///
181  bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) {
182    LLVM_DEBUG(dbgs() << "Machine Function\n"
183                      << "********** EXPANDING POST-RA PSEUDO INSTRS **********\n"
184                      << "********** Function: " << MF.getName() << '\n');
185    TRI = MF.getSubtarget().getRegisterInfo();
186    TII = MF.getSubtarget().getInstrInfo();
187  
188    bool MadeChange = false;
189  
190    for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end();
191         mbbi != mbbe; ++mbbi) {
192      for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end();
193           mi != me;) {
194        MachineInstr &MI = *mi;
195        // Advance iterator here because MI may be erased.
196        ++mi;
197  
198        // Only expand pseudos.
199        if (!MI.isPseudo())
200          continue;
201  
202        // Give targets a chance to expand even standard pseudos.
203        if (TII->expandPostRAPseudo(MI)) {
204          MadeChange = true;
205          continue;
206        }
207  
208        // Expand standard pseudos.
209        switch (MI.getOpcode()) {
210        case TargetOpcode::SUBREG_TO_REG:
211          MadeChange |= LowerSubregToReg(&MI);
212          break;
213        case TargetOpcode::COPY:
214          MadeChange |= LowerCopy(&MI);
215          break;
216        case TargetOpcode::DBG_VALUE:
217          continue;
218        case TargetOpcode::INSERT_SUBREG:
219        case TargetOpcode::EXTRACT_SUBREG:
220          llvm_unreachable("Sub-register pseudos should have been eliminated.");
221        }
222      }
223    }
224  
225    return MadeChange;
226  }
227