1cf4748f1SDan Gohman //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
2cf4748f1SDan Gohman //
3cf4748f1SDan Gohman //                     The LLVM Compiler Infrastructure
4cf4748f1SDan Gohman //
5cf4748f1SDan Gohman // This file is distributed under the University of Illinois Open Source
6cf4748f1SDan Gohman // License. See LICENSE.TXT for details.
7cf4748f1SDan Gohman //
8cf4748f1SDan Gohman //===----------------------------------------------------------------------===//
9cf4748f1SDan Gohman ///
10cf4748f1SDan Gohman /// \file
11cf4748f1SDan Gohman /// \brief This file implements a pass which assigns WebAssembly register
12cf4748f1SDan Gohman /// numbers for CodeGen virtual registers.
13cf4748f1SDan Gohman ///
14cf4748f1SDan Gohman //===----------------------------------------------------------------------===//
15cf4748f1SDan Gohman 
16cf4748f1SDan Gohman #include "WebAssembly.h"
17cf4748f1SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18cf4748f1SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
19cf4748f1SDan Gohman #include "WebAssemblySubtarget.h"
20*4fc4e42dSDan Gohman #include "WebAssemblyUtilities.h"
21cf4748f1SDan Gohman #include "llvm/ADT/SCCIterator.h"
229769debfSDerek Schuff #include "llvm/CodeGen/MachineFrameInfo.h"
2383947569SDan Gohman #include "llvm/CodeGen/MachineFunction.h"
24cf4748f1SDan Gohman #include "llvm/CodeGen/MachineInstrBuilder.h"
25cf4748f1SDan Gohman #include "llvm/CodeGen/MachineLoopInfo.h"
26cf4748f1SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
27cf4748f1SDan Gohman #include "llvm/CodeGen/Passes.h"
28cf4748f1SDan Gohman #include "llvm/Support/Debug.h"
29cf4748f1SDan Gohman #include "llvm/Support/raw_ostream.h"
30cf4748f1SDan Gohman using namespace llvm;
31cf4748f1SDan Gohman 
32cf4748f1SDan Gohman #define DEBUG_TYPE "wasm-reg-numbering"
33cf4748f1SDan Gohman 
34cf4748f1SDan Gohman namespace {
35cf4748f1SDan Gohman class WebAssemblyRegNumbering final : public MachineFunctionPass {
36117296c0SMehdi Amini   StringRef getPassName() const override {
37cf4748f1SDan Gohman     return "WebAssembly Register Numbering";
38cf4748f1SDan Gohman   }
39cf4748f1SDan Gohman 
40cf4748f1SDan Gohman   void getAnalysisUsage(AnalysisUsage &AU) const override {
41cf4748f1SDan Gohman     AU.setPreservesCFG();
42cf4748f1SDan Gohman     MachineFunctionPass::getAnalysisUsage(AU);
43cf4748f1SDan Gohman   }
44cf4748f1SDan Gohman 
45cf4748f1SDan Gohman   bool runOnMachineFunction(MachineFunction &MF) override;
46cf4748f1SDan Gohman 
47cf4748f1SDan Gohman public:
48cf4748f1SDan Gohman   static char ID; // Pass identification, replacement for typeid
49cf4748f1SDan Gohman   WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
50cf4748f1SDan Gohman };
51cf4748f1SDan Gohman } // end anonymous namespace
52cf4748f1SDan Gohman 
53cf4748f1SDan Gohman char WebAssemblyRegNumbering::ID = 0;
54cf4748f1SDan Gohman FunctionPass *llvm::createWebAssemblyRegNumbering() {
55cf4748f1SDan Gohman   return new WebAssemblyRegNumbering();
56cf4748f1SDan Gohman }
57cf4748f1SDan Gohman 
58cf4748f1SDan Gohman bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
59cf4748f1SDan Gohman   DEBUG(dbgs() << "********** Register Numbering **********\n"
60cf4748f1SDan Gohman                   "********** Function: "
61cf4748f1SDan Gohman                << MF.getName() << '\n');
62cf4748f1SDan Gohman 
63cf4748f1SDan Gohman   WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
64cf4748f1SDan Gohman   MachineRegisterInfo &MRI = MF.getRegInfo();
65cf4748f1SDan Gohman 
66cf4748f1SDan Gohman   MFI.initWARegs();
67cf4748f1SDan Gohman 
68cf4748f1SDan Gohman   // WebAssembly argument registers are in the same index space as local
69cf4748f1SDan Gohman   // variables. Assign the numbers for them first.
704ba4816bSDan Gohman   MachineBasicBlock &EntryMBB = MF.front();
714ba4816bSDan Gohman   for (MachineInstr &MI : EntryMBB) {
72*4fc4e42dSDan Gohman     if (!WebAssembly::isArgument(MI))
73*4fc4e42dSDan Gohman       break;
74*4fc4e42dSDan Gohman 
750cfb5f85SDan Gohman     int64_t Imm = MI.getOperand(1).getImm();
7665194682SDerek Schuff     DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg() << " -> WAReg "
770cfb5f85SDan Gohman                  << Imm << "\n");
780cfb5f85SDan Gohman     MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
79cf4748f1SDan Gohman   }
80cf4748f1SDan Gohman 
81cf4748f1SDan Gohman   // Then assign regular WebAssembly registers for all remaining used
8208d58bcfSDan Gohman   // virtual registers. TODO: Consider sorting the registers by frequency of
8308d58bcfSDan Gohman   // use, to maximize usage of small immediate fields.
84cf4748f1SDan Gohman   unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
854ba4816bSDan Gohman   unsigned NumStackRegs = 0;
8665194682SDerek Schuff   // Start the numbering for locals after the arg regs
8765194682SDerek Schuff   unsigned CurReg = MFI.getParams().size();
88cf4748f1SDan Gohman   for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
89cf4748f1SDan Gohman     unsigned VReg = TargetRegisterInfo::index2VirtReg(VRegIdx);
90899cb5abSDan Gohman     // Skip unused registers.
91899cb5abSDan Gohman     if (MRI.use_empty(VReg))
92899cb5abSDan Gohman       continue;
934ba4816bSDan Gohman     // Handle stackified registers.
944ba4816bSDan Gohman     if (MFI.isVRegStackified(VReg)) {
9565194682SDerek Schuff       DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
9665194682SDerek Schuff                    << (INT32_MIN | NumStackRegs) << "\n");
974ba4816bSDan Gohman       MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
984ba4816bSDan Gohman       continue;
994ba4816bSDan Gohman     }
10065194682SDerek Schuff     if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
10165194682SDerek Schuff       DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
10265194682SDerek Schuff       MFI.setWAReg(VReg, CurReg++);
10365194682SDerek Schuff     }
104cf4748f1SDan Gohman   }
105cf4748f1SDan Gohman 
106cf4748f1SDan Gohman   return true;
107cf4748f1SDan Gohman }
108