xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===-- WebAssemblyReplacePhysRegs.cpp - Replace phys regs with virt regs -===//
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 /// \file
100b57cec5SDimitry Andric /// This file implements a pass that replaces physical registers with
110b57cec5SDimitry Andric /// virtual registers.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// LLVM expects certain physical registers, such as a stack pointer. However,
140b57cec5SDimitry Andric /// WebAssembly doesn't actually have such physical registers. This pass is run
150b57cec5SDimitry Andric /// once LLVM no longer needs these registers, and replaces them with virtual
160b57cec5SDimitry Andric /// registers, so they can participate in register stackifying and coloring in
170b57cec5SDimitry Andric /// the normal way.
180b57cec5SDimitry Andric ///
190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
220b57cec5SDimitry Andric #include "WebAssembly.h"
230b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
240b57cec5SDimitry Andric #include "WebAssemblySubtarget.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
280b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-replace-phys-regs"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric namespace {
350b57cec5SDimitry Andric class WebAssemblyReplacePhysRegs final : public MachineFunctionPass {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
WebAssemblyReplacePhysRegs()380b57cec5SDimitry Andric   WebAssemblyReplacePhysRegs() : MachineFunctionPass(ID) {}
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric private:
getPassName() const410b57cec5SDimitry Andric   StringRef getPassName() const override {
420b57cec5SDimitry Andric     return "WebAssembly Replace Physical Registers";
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const450b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
460b57cec5SDimitry Andric     AU.setPreservesCFG();
470b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
510b57cec5SDimitry Andric };
520b57cec5SDimitry Andric } // end anonymous namespace
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric char WebAssemblyReplacePhysRegs::ID = 0;
550b57cec5SDimitry Andric INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
560b57cec5SDimitry Andric                 "Replace physical registers with virtual registers", false,
570b57cec5SDimitry Andric                 false)
580b57cec5SDimitry Andric 
createWebAssemblyReplacePhysRegs()590b57cec5SDimitry Andric FunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
600b57cec5SDimitry Andric   return new WebAssemblyReplacePhysRegs();
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)630b57cec5SDimitry Andric bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
640b57cec5SDimitry Andric   LLVM_DEBUG({
650b57cec5SDimitry Andric     dbgs() << "********** Replace Physical Registers **********\n"
660b57cec5SDimitry Andric            << "********** Function: " << MF.getName() << '\n';
670b57cec5SDimitry Andric   });
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
705ffd83dbSDimitry Andric   auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
710b57cec5SDimitry Andric   bool Changed = false;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
740b57cec5SDimitry Andric          "LiveIntervals shouldn't be active yet!");
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   for (unsigned PReg = WebAssembly::NoRegister + 1;
770b57cec5SDimitry Andric        PReg < WebAssembly::NUM_TARGET_REGS; ++PReg) {
780b57cec5SDimitry Andric     // Skip fake registers that are never used explicitly.
790b57cec5SDimitry Andric     if (PReg == WebAssembly::VALUE_STACK || PReg == WebAssembly::ARGUMENTS)
800b57cec5SDimitry Andric       continue;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     // Replace explicit uses of the physical register with a virtual register.
830b57cec5SDimitry Andric     const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
840b57cec5SDimitry Andric     unsigned VReg = WebAssembly::NoRegister;
85*349cc55cSDimitry Andric     for (MachineOperand &MO :
86*349cc55cSDimitry Andric          llvm::make_early_inc_range(MRI.reg_operands(PReg))) {
870b57cec5SDimitry Andric       if (!MO.isImplicit()) {
885ffd83dbSDimitry Andric         if (VReg == WebAssembly::NoRegister) {
890b57cec5SDimitry Andric           VReg = MRI.createVirtualRegister(RC);
905ffd83dbSDimitry Andric           if (PReg == TRI.getFrameRegister(MF)) {
915ffd83dbSDimitry Andric             auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
925ffd83dbSDimitry Andric             assert(!FI->isFrameBaseVirtual());
935ffd83dbSDimitry Andric             FI->setFrameBaseVreg(VReg);
945ffd83dbSDimitry Andric             LLVM_DEBUG({
955ffd83dbSDimitry Andric               dbgs() << "replacing preg " << PReg << " with " << VReg << " ("
965ffd83dbSDimitry Andric                      << Register::virtReg2Index(VReg) << ")\n";
975ffd83dbSDimitry Andric             });
985ffd83dbSDimitry Andric           }
995ffd83dbSDimitry Andric         }
1000b57cec5SDimitry Andric         MO.setReg(VReg);
1010b57cec5SDimitry Andric         Changed = true;
1020b57cec5SDimitry Andric       }
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   return Changed;
1070b57cec5SDimitry Andric }
108