1303231Sdim//===-- WebAssemblyReplacePhysRegs.cpp - Replace phys regs with virt regs -===//
2303231Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303231Sdim//
7303231Sdim//===----------------------------------------------------------------------===//
8303231Sdim///
9303231Sdim/// \file
10341825Sdim/// This file implements a pass that replaces physical registers with
11303231Sdim/// virtual registers.
12303231Sdim///
13303231Sdim/// LLVM expects certain physical registers, such as a stack pointer. However,
14303231Sdim/// WebAssembly doesn't actually have such physical registers. This pass is run
15303231Sdim/// once LLVM no longer needs these registers, and replaces them with virtual
16303231Sdim/// registers, so they can participate in register stackifying and coloring in
17303231Sdim/// the normal way.
18303231Sdim///
19303231Sdim//===----------------------------------------------------------------------===//
20303231Sdim
21321369Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
22303231Sdim#include "WebAssembly.h"
23303231Sdim#include "WebAssemblyMachineFunctionInfo.h"
24303231Sdim#include "WebAssemblySubtarget.h"
25303231Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
26303231Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
27303231Sdim#include "llvm/CodeGen/Passes.h"
28303231Sdim#include "llvm/Support/Debug.h"
29303231Sdim#include "llvm/Support/raw_ostream.h"
30303231Sdimusing namespace llvm;
31303231Sdim
32303231Sdim#define DEBUG_TYPE "wasm-replace-phys-regs"
33303231Sdim
34303231Sdimnamespace {
35303231Sdimclass WebAssemblyReplacePhysRegs final : public MachineFunctionPass {
36303231Sdimpublic:
37303231Sdim  static char ID; // Pass identification, replacement for typeid
38303231Sdim  WebAssemblyReplacePhysRegs() : MachineFunctionPass(ID) {}
39303231Sdim
40303231Sdimprivate:
41314564Sdim  StringRef getPassName() const override {
42303231Sdim    return "WebAssembly Replace Physical Registers";
43303231Sdim  }
44303231Sdim
45303231Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
46303231Sdim    AU.setPreservesCFG();
47303231Sdim    MachineFunctionPass::getAnalysisUsage(AU);
48303231Sdim  }
49303231Sdim
50303231Sdim  bool runOnMachineFunction(MachineFunction &MF) override;
51303231Sdim};
52303231Sdim} // end anonymous namespace
53303231Sdim
54303231Sdimchar WebAssemblyReplacePhysRegs::ID = 0;
55341825SdimINITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
56344779Sdim                "Replace physical registers with virtual registers", false,
57344779Sdim                false)
58341825Sdim
59303231SdimFunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
60303231Sdim  return new WebAssemblyReplacePhysRegs();
61303231Sdim}
62303231Sdim
63303231Sdimbool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
64341825Sdim  LLVM_DEBUG({
65303231Sdim    dbgs() << "********** Replace Physical Registers **********\n"
66303231Sdim           << "********** Function: " << MF.getName() << '\n';
67303231Sdim  });
68303231Sdim
69303231Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
70303231Sdim  const auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
71303231Sdim  bool Changed = false;
72303231Sdim
73303231Sdim  assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
74303231Sdim         "LiveIntervals shouldn't be active yet!");
75303231Sdim  // We don't preserve SSA or liveness.
76303231Sdim  MRI.leaveSSA();
77303231Sdim  MRI.invalidateLiveness();
78303231Sdim
79303231Sdim  for (unsigned PReg = WebAssembly::NoRegister + 1;
80303231Sdim       PReg < WebAssembly::NUM_TARGET_REGS; ++PReg) {
81303231Sdim    // Skip fake registers that are never used explicitly.
82314564Sdim    if (PReg == WebAssembly::VALUE_STACK || PReg == WebAssembly::ARGUMENTS)
83303231Sdim      continue;
84303231Sdim
85303231Sdim    // Replace explicit uses of the physical register with a virtual register.
86303231Sdim    const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
87303231Sdim    unsigned VReg = WebAssembly::NoRegister;
88344779Sdim    for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E;) {
89303231Sdim      MachineOperand &MO = *I++;
90303231Sdim      if (!MO.isImplicit()) {
91303231Sdim        if (VReg == WebAssembly::NoRegister)
92303231Sdim          VReg = MRI.createVirtualRegister(RC);
93303231Sdim        MO.setReg(VReg);
94314564Sdim        if (MO.getParent()->isDebugValue())
95314564Sdim          MO.setIsDebug();
96303231Sdim        Changed = true;
97303231Sdim      }
98303231Sdim    }
99303231Sdim  }
100303231Sdim
101303231Sdim  return Changed;
102303231Sdim}
103