1dd58ef01SDimitry Andric //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
2dd58ef01SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dd58ef01SDimitry Andric //
7dd58ef01SDimitry Andric //===----------------------------------------------------------------------===//
8dd58ef01SDimitry Andric ///
9dd58ef01SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// This file implements a pass which assigns WebAssembly register
11dd58ef01SDimitry Andric /// numbers for CodeGen virtual registers.
12dd58ef01SDimitry Andric ///
13dd58ef01SDimitry Andric //===----------------------------------------------------------------------===//
14dd58ef01SDimitry Andric
15dd58ef01SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
167ab83427SDimitry Andric #include "WebAssembly.h"
17dd58ef01SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
18dd58ef01SDimitry Andric #include "WebAssemblySubtarget.h"
19b1c73532SDimitry Andric #include "WebAssemblyUtilities.h"
20dd58ef01SDimitry Andric #include "llvm/ADT/SCCIterator.h"
21dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
2201095a5dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
23dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
24dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
25dd58ef01SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
26dd58ef01SDimitry Andric #include "llvm/CodeGen/Passes.h"
27dd58ef01SDimitry Andric #include "llvm/Support/Debug.h"
28dd58ef01SDimitry Andric #include "llvm/Support/raw_ostream.h"
29dd58ef01SDimitry Andric using namespace llvm;
30dd58ef01SDimitry Andric
31dd58ef01SDimitry Andric #define DEBUG_TYPE "wasm-reg-numbering"
32dd58ef01SDimitry Andric
33dd58ef01SDimitry Andric namespace {
34dd58ef01SDimitry Andric class WebAssemblyRegNumbering final : public MachineFunctionPass {
getPassName() const35b915e9e0SDimitry Andric StringRef getPassName() const override {
36dd58ef01SDimitry Andric return "WebAssembly Register Numbering";
37dd58ef01SDimitry Andric }
38dd58ef01SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const39dd58ef01SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
40dd58ef01SDimitry Andric AU.setPreservesCFG();
41dd58ef01SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
42dd58ef01SDimitry Andric }
43dd58ef01SDimitry Andric
44dd58ef01SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
45dd58ef01SDimitry Andric
46dd58ef01SDimitry Andric public:
47dd58ef01SDimitry Andric static char ID; // Pass identification, replacement for typeid
WebAssemblyRegNumbering()48dd58ef01SDimitry Andric WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
49dd58ef01SDimitry Andric };
50dd58ef01SDimitry Andric } // end anonymous namespace
51dd58ef01SDimitry Andric
52dd58ef01SDimitry Andric char WebAssemblyRegNumbering::ID = 0;
53eb11fae6SDimitry Andric INITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE,
54eb11fae6SDimitry Andric "Assigns WebAssembly register numbers for virtual registers",
55eb11fae6SDimitry Andric false, false)
56eb11fae6SDimitry Andric
createWebAssemblyRegNumbering()57dd58ef01SDimitry Andric FunctionPass *llvm::createWebAssemblyRegNumbering() {
58dd58ef01SDimitry Andric return new WebAssemblyRegNumbering();
59dd58ef01SDimitry Andric }
60dd58ef01SDimitry Andric
runOnMachineFunction(MachineFunction & MF)61dd58ef01SDimitry Andric bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
62eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n"
63dd58ef01SDimitry Andric "********** Function: "
64dd58ef01SDimitry Andric << MF.getName() << '\n');
65dd58ef01SDimitry Andric
66dd58ef01SDimitry Andric WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
67dd58ef01SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
68dd58ef01SDimitry Andric
69cfca06d7SDimitry Andric MFI.initWARegs(MRI);
70dd58ef01SDimitry Andric
71dd58ef01SDimitry Andric // WebAssembly argument registers are in the same index space as local
72dd58ef01SDimitry Andric // variables. Assign the numbers for them first.
73dd58ef01SDimitry Andric MachineBasicBlock &EntryMBB = MF.front();
74dd58ef01SDimitry Andric for (MachineInstr &MI : EntryMBB) {
75e6d15924SDimitry Andric if (!WebAssembly::isArgument(MI.getOpcode()))
76b915e9e0SDimitry Andric break;
77b915e9e0SDimitry Andric
7801095a5dSDimitry Andric int64_t Imm = MI.getOperand(1).getImm();
79eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg()
80eb11fae6SDimitry Andric << " -> WAReg " << Imm << "\n");
8101095a5dSDimitry Andric MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
82dd58ef01SDimitry Andric }
83dd58ef01SDimitry Andric
84dd58ef01SDimitry Andric // Then assign regular WebAssembly registers for all remaining used
85dd58ef01SDimitry Andric // virtual registers. TODO: Consider sorting the registers by frequency of
86dd58ef01SDimitry Andric // use, to maximize usage of small immediate fields.
87dd58ef01SDimitry Andric unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
88dd58ef01SDimitry Andric unsigned NumStackRegs = 0;
8901095a5dSDimitry Andric // Start the numbering for locals after the arg regs
9001095a5dSDimitry Andric unsigned CurReg = MFI.getParams().size();
91dd58ef01SDimitry Andric for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
926f8fc217SDimitry Andric Register VReg = Register::index2VirtReg(VRegIdx);
93dd58ef01SDimitry Andric // Skip unused registers.
94dd58ef01SDimitry Andric if (MRI.use_empty(VReg))
95dd58ef01SDimitry Andric continue;
9601095a5dSDimitry Andric // Handle stackified registers.
9701095a5dSDimitry Andric if (MFI.isVRegStackified(VReg)) {
98eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
9901095a5dSDimitry Andric << (INT32_MIN | NumStackRegs) << "\n");
10001095a5dSDimitry Andric MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
10101095a5dSDimitry Andric continue;
102dd58ef01SDimitry Andric }
103b1c73532SDimitry Andric if (MFI.getWAReg(VReg) == WebAssembly::UnusedReg) {
104eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
10501095a5dSDimitry Andric MFI.setWAReg(VReg, CurReg++);
10601095a5dSDimitry Andric }
10701095a5dSDimitry Andric }
108dd58ef01SDimitry Andric
109dd58ef01SDimitry Andric return true;
110dd58ef01SDimitry Andric }
111