WebAssemblyRegNumbering.cpp revision 309124
1292915Sdim//===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
2292915Sdim//
3292915Sdim//                     The LLVM Compiler Infrastructure
4292915Sdim//
5292915Sdim// This file is distributed under the University of Illinois Open Source
6292915Sdim// License. See LICENSE.TXT for details.
7292915Sdim//
8292915Sdim//===----------------------------------------------------------------------===//
9292915Sdim///
10292915Sdim/// \file
11292915Sdim/// \brief This file implements a pass which assigns WebAssembly register
12292915Sdim/// numbers for CodeGen virtual registers.
13292915Sdim///
14292915Sdim//===----------------------------------------------------------------------===//
15292915Sdim
16292915Sdim#include "WebAssembly.h"
17292915Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18292915Sdim#include "WebAssemblyMachineFunctionInfo.h"
19292915Sdim#include "WebAssemblySubtarget.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 {
35292915Sdim  const char *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;
53292915SdimFunctionPass *llvm::createWebAssemblyRegNumbering() {
54292915Sdim  return new WebAssemblyRegNumbering();
55292915Sdim}
56292915Sdim
57292915Sdimbool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
58292915Sdim  DEBUG(dbgs() << "********** Register Numbering **********\n"
59292915Sdim                  "********** Function: "
60292915Sdim               << MF.getName() << '\n');
61292915Sdim
62292915Sdim  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
63292915Sdim  MachineRegisterInfo &MRI = MF.getRegInfo();
64292915Sdim
65292915Sdim  MFI.initWARegs();
66292915Sdim
67292915Sdim  // WebAssembly argument registers are in the same index space as local
68292915Sdim  // variables. Assign the numbers for them first.
69292915Sdim  MachineBasicBlock &EntryMBB = MF.front();
70292915Sdim  for (MachineInstr &MI : EntryMBB) {
71292915Sdim    switch (MI.getOpcode()) {
72292915Sdim    case WebAssembly::ARGUMENT_I32:
73292915Sdim    case WebAssembly::ARGUMENT_I64:
74292915Sdim    case WebAssembly::ARGUMENT_F32:
75309124Sdim    case WebAssembly::ARGUMENT_F64: {
76309124Sdim      int64_t Imm = MI.getOperand(1).getImm();
77309124Sdim      DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg() << " -> WAReg "
78309124Sdim                   << Imm << "\n");
79309124Sdim      MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
80292915Sdim      break;
81309124Sdim    }
82292915Sdim    default:
83292915Sdim      break;
84292915Sdim    }
85292915Sdim  }
86292915Sdim
87292915Sdim  // Then assign regular WebAssembly registers for all remaining used
88292915Sdim  // virtual registers. TODO: Consider sorting the registers by frequency of
89292915Sdim  // use, to maximize usage of small immediate fields.
90292915Sdim  unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
91292915Sdim  unsigned NumStackRegs = 0;
92309124Sdim  // Start the numbering for locals after the arg regs
93309124Sdim  unsigned CurReg = MFI.getParams().size();
94292915Sdim  for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
95292915Sdim    unsigned VReg = TargetRegisterInfo::index2VirtReg(VRegIdx);
96309124Sdim    // Skip unused registers.
97309124Sdim    if (MRI.use_empty(VReg))
98309124Sdim      continue;
99292915Sdim    // Handle stackified registers.
100292915Sdim    if (MFI.isVRegStackified(VReg)) {
101309124Sdim      DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
102309124Sdim                   << (INT32_MIN | NumStackRegs) << "\n");
103292915Sdim      MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
104292915Sdim      continue;
105292915Sdim    }
106309124Sdim    if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
107309124Sdim      DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
108309124Sdim      MFI.setWAReg(VReg, CurReg++);
109309124Sdim    }
110292915Sdim  }
111292915Sdim
112292915Sdim  return true;
113292915Sdim}
114