17d523365SDimitry Andric //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric //                     The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric ///
107d523365SDimitry Andric /// \file
11*4ba319b5SDimitry Andric /// This file implements a pass which assigns WebAssembly register
127d523365SDimitry Andric /// numbers for CodeGen virtual registers.
137d523365SDimitry Andric ///
147d523365SDimitry Andric //===----------------------------------------------------------------------===//
157d523365SDimitry Andric 
167d523365SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17db17bf38SDimitry Andric #include "WebAssembly.h"
187d523365SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
197d523365SDimitry Andric #include "WebAssemblySubtarget.h"
20d88c1a5aSDimitry Andric #include "WebAssemblyUtilities.h"
217d523365SDimitry Andric #include "llvm/ADT/SCCIterator.h"
227d523365SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
233ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
247d523365SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
257d523365SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
267d523365SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
277d523365SDimitry Andric #include "llvm/CodeGen/Passes.h"
287d523365SDimitry Andric #include "llvm/Support/Debug.h"
297d523365SDimitry Andric #include "llvm/Support/raw_ostream.h"
307d523365SDimitry Andric using namespace llvm;
317d523365SDimitry Andric 
327d523365SDimitry Andric #define DEBUG_TYPE "wasm-reg-numbering"
337d523365SDimitry Andric 
347d523365SDimitry Andric namespace {
357d523365SDimitry Andric class WebAssemblyRegNumbering final : public MachineFunctionPass {
getPassName() const36d88c1a5aSDimitry Andric   StringRef getPassName() const override {
377d523365SDimitry Andric     return "WebAssembly Register Numbering";
387d523365SDimitry Andric   }
397d523365SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const407d523365SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
417d523365SDimitry Andric     AU.setPreservesCFG();
427d523365SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
437d523365SDimitry Andric   }
447d523365SDimitry Andric 
457d523365SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
467d523365SDimitry Andric 
477d523365SDimitry Andric public:
487d523365SDimitry Andric   static char ID; // Pass identification, replacement for typeid
WebAssemblyRegNumbering()497d523365SDimitry Andric   WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
507d523365SDimitry Andric };
517d523365SDimitry Andric } // end anonymous namespace
527d523365SDimitry Andric 
537d523365SDimitry Andric char WebAssemblyRegNumbering::ID = 0;
54*4ba319b5SDimitry Andric INITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE,
55*4ba319b5SDimitry Andric                 "Assigns WebAssembly register numbers for virtual registers",
56*4ba319b5SDimitry Andric                 false, false)
57*4ba319b5SDimitry Andric 
createWebAssemblyRegNumbering()587d523365SDimitry Andric FunctionPass *llvm::createWebAssemblyRegNumbering() {
597d523365SDimitry Andric   return new WebAssemblyRegNumbering();
607d523365SDimitry Andric }
617d523365SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)627d523365SDimitry Andric bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
63*4ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n"
647d523365SDimitry Andric                        "********** Function: "
657d523365SDimitry Andric                     << MF.getName() << '\n');
667d523365SDimitry Andric 
677d523365SDimitry Andric   WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
687d523365SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
697d523365SDimitry Andric 
707d523365SDimitry Andric   MFI.initWARegs();
717d523365SDimitry Andric 
727d523365SDimitry Andric   // WebAssembly argument registers are in the same index space as local
737d523365SDimitry Andric   // variables. Assign the numbers for them first.
747d523365SDimitry Andric   MachineBasicBlock &EntryMBB = MF.front();
757d523365SDimitry Andric   for (MachineInstr &MI : EntryMBB) {
76d88c1a5aSDimitry Andric     if (!WebAssembly::isArgument(MI))
77d88c1a5aSDimitry Andric       break;
78d88c1a5aSDimitry Andric 
793ca95b02SDimitry Andric     int64_t Imm = MI.getOperand(1).getImm();
80*4ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg()
81*4ba319b5SDimitry Andric                       << " -> WAReg " << Imm << "\n");
823ca95b02SDimitry Andric     MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
837d523365SDimitry Andric   }
847d523365SDimitry Andric 
857d523365SDimitry Andric   // Then assign regular WebAssembly registers for all remaining used
867d523365SDimitry Andric   // virtual registers. TODO: Consider sorting the registers by frequency of
877d523365SDimitry Andric   // use, to maximize usage of small immediate fields.
887d523365SDimitry Andric   unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
897d523365SDimitry Andric   unsigned NumStackRegs = 0;
903ca95b02SDimitry Andric   // Start the numbering for locals after the arg regs
913ca95b02SDimitry Andric   unsigned CurReg = MFI.getParams().size();
927d523365SDimitry Andric   for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
937d523365SDimitry Andric     unsigned VReg = TargetRegisterInfo::index2VirtReg(VRegIdx);
947d523365SDimitry Andric     // Skip unused registers.
957d523365SDimitry Andric     if (MRI.use_empty(VReg))
967d523365SDimitry Andric       continue;
973ca95b02SDimitry Andric     // Handle stackified registers.
983ca95b02SDimitry Andric     if (MFI.isVRegStackified(VReg)) {
99*4ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
1003ca95b02SDimitry Andric                         << (INT32_MIN | NumStackRegs) << "\n");
1013ca95b02SDimitry Andric       MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
1023ca95b02SDimitry Andric       continue;
1037d523365SDimitry Andric     }
1043ca95b02SDimitry Andric     if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
105*4ba319b5SDimitry Andric       LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
1063ca95b02SDimitry Andric       MFI.setWAReg(VReg, CurReg++);
1073ca95b02SDimitry Andric     }
1083ca95b02SDimitry Andric   }
1097d523365SDimitry Andric 
1107d523365SDimitry Andric   return true;
1117d523365SDimitry Andric }
112