1292915Sdim//===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
2292915Sdim//
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
6292915Sdim//
7292915Sdim//===----------------------------------------------------------------------===//
8292915Sdim///
9292915Sdim/// \file
10341825Sdim/// This file implements a pass which assigns WebAssembly register
11292915Sdim/// numbers for CodeGen virtual registers.
12292915Sdim///
13292915Sdim//===----------------------------------------------------------------------===//
14292915Sdim
15321369Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16292915Sdim#include "WebAssembly.h"
17292915Sdim#include "WebAssemblyMachineFunctionInfo.h"
18292915Sdim#include "WebAssemblySubtarget.h"
19314564Sdim#include "WebAssemblyUtilities.h"
20292915Sdim#include "llvm/ADT/SCCIterator.h"
21309124Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
22292915Sdim#include "llvm/CodeGen/MachineFunction.h"
23292915Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
24292915Sdim#include "llvm/CodeGen/MachineLoopInfo.h"
25292915Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
26292915Sdim#include "llvm/CodeGen/Passes.h"
27292915Sdim#include "llvm/Support/Debug.h"
28292915Sdim#include "llvm/Support/raw_ostream.h"
29292915Sdimusing namespace llvm;
30292915Sdim
31292915Sdim#define DEBUG_TYPE "wasm-reg-numbering"
32292915Sdim
33292915Sdimnamespace {
34292915Sdimclass WebAssemblyRegNumbering final : public MachineFunctionPass {
35314564Sdim  StringRef getPassName() const override {
36292915Sdim    return "WebAssembly Register Numbering";
37292915Sdim  }
38292915Sdim
39292915Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
40292915Sdim    AU.setPreservesCFG();
41292915Sdim    MachineFunctionPass::getAnalysisUsage(AU);
42292915Sdim  }
43292915Sdim
44292915Sdim  bool runOnMachineFunction(MachineFunction &MF) override;
45292915Sdim
46292915Sdimpublic:
47292915Sdim  static char ID; // Pass identification, replacement for typeid
48292915Sdim  WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
49292915Sdim};
50292915Sdim} // end anonymous namespace
51292915Sdim
52292915Sdimchar WebAssemblyRegNumbering::ID = 0;
53341825SdimINITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE,
54341825Sdim                "Assigns WebAssembly register numbers for virtual registers",
55341825Sdim                false, false)
56341825Sdim
57292915SdimFunctionPass *llvm::createWebAssemblyRegNumbering() {
58292915Sdim  return new WebAssemblyRegNumbering();
59292915Sdim}
60292915Sdim
61292915Sdimbool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
62341825Sdim  LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n"
63341825Sdim                       "********** Function: "
64341825Sdim                    << MF.getName() << '\n');
65292915Sdim
66292915Sdim  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
67292915Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
68292915Sdim
69292915Sdim  MFI.initWARegs();
70292915Sdim
71292915Sdim  // WebAssembly argument registers are in the same index space as local
72292915Sdim  // variables. Assign the numbers for them first.
73292915Sdim  MachineBasicBlock &EntryMBB = MF.front();
74292915Sdim  for (MachineInstr &MI : EntryMBB) {
75353358Sdim    if (!WebAssembly::isArgument(MI.getOpcode()))
76292915Sdim      break;
77314564Sdim
78314564Sdim    int64_t Imm = MI.getOperand(1).getImm();
79341825Sdim    LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg()
80341825Sdim                      << " -> WAReg " << Imm << "\n");
81314564Sdim    MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
82292915Sdim  }
83292915Sdim
84292915Sdim  // Then assign regular WebAssembly registers for all remaining used
85292915Sdim  // virtual registers. TODO: Consider sorting the registers by frequency of
86292915Sdim  // use, to maximize usage of small immediate fields.
87292915Sdim  unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
88292915Sdim  unsigned NumStackRegs = 0;
89309124Sdim  // Start the numbering for locals after the arg regs
90309124Sdim  unsigned CurReg = MFI.getParams().size();
91292915Sdim  for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
92360784Sdim    unsigned VReg = Register::index2VirtReg(VRegIdx);
93309124Sdim    // Skip unused registers.
94309124Sdim    if (MRI.use_empty(VReg))
95309124Sdim      continue;
96292915Sdim    // Handle stackified registers.
97292915Sdim    if (MFI.isVRegStackified(VReg)) {
98341825Sdim      LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
99341825Sdim                        << (INT32_MIN | NumStackRegs) << "\n");
100292915Sdim      MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
101292915Sdim      continue;
102292915Sdim    }
103309124Sdim    if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
104341825Sdim      LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
105309124Sdim      MFI.setWAReg(VReg, CurReg++);
106309124Sdim    }
107292915Sdim  }
108292915Sdim
109292915Sdim  return true;
110292915Sdim}
111