1cf4748f1SDan Gohman //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
2cf4748f1SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf4748f1SDan Gohman //
7cf4748f1SDan Gohman //===----------------------------------------------------------------------===//
8cf4748f1SDan Gohman ///
9cf4748f1SDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file implements a pass which assigns WebAssembly register
11cf4748f1SDan Gohman /// numbers for CodeGen virtual registers.
12cf4748f1SDan Gohman ///
13cf4748f1SDan Gohman //===----------------------------------------------------------------------===//
14cf4748f1SDan Gohman 
15cf4748f1SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
160b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h"
176bda14b3SChandler Carruth #include "WebAssembly.h"
18cf4748f1SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
19cf4748f1SDan Gohman #include "WebAssemblySubtarget.h"
20cf4748f1SDan Gohman #include "llvm/ADT/SCCIterator.h"
219769debfSDerek Schuff #include "llvm/CodeGen/MachineFrameInfo.h"
2283947569SDan Gohman #include "llvm/CodeGen/MachineFunction.h"
23cf4748f1SDan Gohman #include "llvm/CodeGen/MachineInstrBuilder.h"
24cf4748f1SDan Gohman #include "llvm/CodeGen/MachineLoopInfo.h"
25cf4748f1SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
26cf4748f1SDan Gohman #include "llvm/CodeGen/Passes.h"
27cf4748f1SDan Gohman #include "llvm/Support/Debug.h"
28cf4748f1SDan Gohman #include "llvm/Support/raw_ostream.h"
29cf4748f1SDan Gohman using namespace llvm;
30cf4748f1SDan Gohman 
31cf4748f1SDan Gohman #define DEBUG_TYPE "wasm-reg-numbering"
32cf4748f1SDan Gohman 
33cf4748f1SDan Gohman namespace {
34cf4748f1SDan Gohman class WebAssemblyRegNumbering final : public MachineFunctionPass {
getPassName() const35117296c0SMehdi Amini   StringRef getPassName() const override {
36cf4748f1SDan Gohman     return "WebAssembly Register Numbering";
37cf4748f1SDan Gohman   }
38cf4748f1SDan Gohman 
getAnalysisUsage(AnalysisUsage & AU) const39cf4748f1SDan Gohman   void getAnalysisUsage(AnalysisUsage &AU) const override {
40cf4748f1SDan Gohman     AU.setPreservesCFG();
41cf4748f1SDan Gohman     MachineFunctionPass::getAnalysisUsage(AU);
42cf4748f1SDan Gohman   }
43cf4748f1SDan Gohman 
44cf4748f1SDan Gohman   bool runOnMachineFunction(MachineFunction &MF) override;
45cf4748f1SDan Gohman 
46cf4748f1SDan Gohman public:
47cf4748f1SDan Gohman   static char ID; // Pass identification, replacement for typeid
WebAssemblyRegNumbering()48cf4748f1SDan Gohman   WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
49cf4748f1SDan Gohman };
50cf4748f1SDan Gohman } // end anonymous namespace
51cf4748f1SDan Gohman 
52cf4748f1SDan Gohman char WebAssemblyRegNumbering::ID = 0;
5340926451SJacob Gravelle INITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE,
5440926451SJacob Gravelle                 "Assigns WebAssembly register numbers for virtual registers",
5540926451SJacob Gravelle                 false, false)
5640926451SJacob Gravelle 
createWebAssemblyRegNumbering()57cf4748f1SDan Gohman FunctionPass *llvm::createWebAssemblyRegNumbering() {
58cf4748f1SDan Gohman   return new WebAssemblyRegNumbering();
59cf4748f1SDan Gohman }
60cf4748f1SDan Gohman 
runOnMachineFunction(MachineFunction & MF)61cf4748f1SDan Gohman bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
62d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n"
63cf4748f1SDan Gohman                        "********** Function: "
64cf4748f1SDan Gohman                     << MF.getName() << '\n');
65cf4748f1SDan Gohman 
66cf4748f1SDan Gohman   WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
67cf4748f1SDan Gohman   MachineRegisterInfo &MRI = MF.getRegInfo();
68cf4748f1SDan Gohman 
69c5d24009SMatt Arsenault   MFI.initWARegs(MRI);
70cf4748f1SDan Gohman 
71cf4748f1SDan Gohman   // WebAssembly argument registers are in the same index space as local
72cf4748f1SDan Gohman   // variables. Assign the numbers for them first.
734ba4816bSDan Gohman   MachineBasicBlock &EntryMBB = MF.front();
744ba4816bSDan Gohman   for (MachineInstr &MI : EntryMBB) {
75d8ddf839SWouter van Oortmerssen     if (!WebAssembly::isArgument(MI.getOpcode()))
764fc4e42dSDan Gohman       break;
774fc4e42dSDan Gohman 
780cfb5f85SDan Gohman     int64_t Imm = MI.getOperand(1).getImm();
79d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg()
80d34e60caSNicola Zaghen                       << " -> WAReg " << Imm << "\n");
810cfb5f85SDan Gohman     MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
82cf4748f1SDan Gohman   }
83cf4748f1SDan Gohman 
84cf4748f1SDan Gohman   // Then assign regular WebAssembly registers for all remaining used
8508d58bcfSDan Gohman   // virtual registers. TODO: Consider sorting the registers by frequency of
8608d58bcfSDan Gohman   // use, to maximize usage of small immediate fields.
87cf4748f1SDan Gohman   unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
884ba4816bSDan Gohman   unsigned NumStackRegs = 0;
8965194682SDerek Schuff   // Start the numbering for locals after the arg regs
9065194682SDerek Schuff   unsigned CurReg = MFI.getParams().size();
91cf4748f1SDan Gohman   for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
92*d6b07348SJim Lin     Register VReg = Register::index2VirtReg(VRegIdx);
93899cb5abSDan Gohman     // Skip unused registers.
94899cb5abSDan Gohman     if (MRI.use_empty(VReg))
95899cb5abSDan Gohman       continue;
964ba4816bSDan Gohman     // Handle stackified registers.
974ba4816bSDan Gohman     if (MFI.isVRegStackified(VReg)) {
98d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
9965194682SDerek Schuff                         << (INT32_MIN | NumStackRegs) << "\n");
1004ba4816bSDan Gohman       MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
1014ba4816bSDan Gohman       continue;
1024ba4816bSDan Gohman     }
10365194682SDerek Schuff     if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
104d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
10565194682SDerek Schuff       MFI.setWAReg(VReg, CurReg++);
10665194682SDerek Schuff     }
107cf4748f1SDan Gohman   }
108cf4748f1SDan Gohman 
109cf4748f1SDan Gohman   return true;
110cf4748f1SDan Gohman }
111