Home | History | Annotate | Download | only in WebAssembly
      1 //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief This file implements a pass which assigns WebAssembly register
     12 /// numbers for CodeGen virtual registers.
     13 ///
     14 //===----------------------------------------------------------------------===//
     15 
     16 #include "WebAssembly.h"
     17 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
     18 #include "WebAssemblyMachineFunctionInfo.h"
     19 #include "WebAssemblySubtarget.h"
     20 #include "llvm/ADT/SCCIterator.h"
     21 #include "llvm/CodeGen/MachineFrameInfo.h"
     22 #include "llvm/CodeGen/MachineFunction.h"
     23 #include "llvm/CodeGen/MachineInstrBuilder.h"
     24 #include "llvm/CodeGen/MachineLoopInfo.h"
     25 #include "llvm/CodeGen/MachineRegisterInfo.h"
     26 #include "llvm/CodeGen/Passes.h"
     27 #include "llvm/Support/Debug.h"
     28 #include "llvm/Support/raw_ostream.h"
     29 using namespace llvm;
     30 
     31 #define DEBUG_TYPE "wasm-reg-numbering"
     32 
     33 namespace {
     34 class WebAssemblyRegNumbering final : public MachineFunctionPass {
     35   const char *getPassName() const override {
     36     return "WebAssembly Register Numbering";
     37   }
     38 
     39   void getAnalysisUsage(AnalysisUsage &AU) const override {
     40     AU.setPreservesCFG();
     41     MachineFunctionPass::getAnalysisUsage(AU);
     42   }
     43 
     44   bool runOnMachineFunction(MachineFunction &MF) override;
     45 
     46 public:
     47   static char ID; // Pass identification, replacement for typeid
     48   WebAssemblyRegNumbering() : MachineFunctionPass(ID) {}
     49 };
     50 } // end anonymous namespace
     51 
     52 char WebAssemblyRegNumbering::ID = 0;
     53 FunctionPass *llvm::createWebAssemblyRegNumbering() {
     54   return new WebAssemblyRegNumbering();
     55 }
     56 
     57 bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) {
     58   DEBUG(dbgs() << "********** Register Numbering **********\n"
     59                   "********** Function: "
     60                << MF.getName() << '\n');
     61 
     62   WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
     63   MachineRegisterInfo &MRI = MF.getRegInfo();
     64 
     65   MFI.initWARegs();
     66 
     67   // WebAssembly argument registers are in the same index space as local
     68   // variables. Assign the numbers for them first.
     69   MachineBasicBlock &EntryMBB = MF.front();
     70   for (MachineInstr &MI : EntryMBB) {
     71     switch (MI.getOpcode()) {
     72     case WebAssembly::ARGUMENT_I32:
     73     case WebAssembly::ARGUMENT_I64:
     74     case WebAssembly::ARGUMENT_F32:
     75     case WebAssembly::ARGUMENT_F64: {
     76       int64_t Imm = MI.getOperand(1).getImm();
     77       DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg() << " -> WAReg "
     78                    << Imm << "\n");
     79       MFI.setWAReg(MI.getOperand(0).getReg(), Imm);
     80       break;
     81     }
     82     default:
     83       break;
     84     }
     85   }
     86 
     87   // Then assign regular WebAssembly registers for all remaining used
     88   // virtual registers. TODO: Consider sorting the registers by frequency of
     89   // use, to maximize usage of small immediate fields.
     90   unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs();
     91   unsigned NumStackRegs = 0;
     92   // Start the numbering for locals after the arg regs
     93   unsigned CurReg = MFI.getParams().size();
     94   for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) {
     95     unsigned VReg = TargetRegisterInfo::index2VirtReg(VRegIdx);
     96     // Skip unused registers.
     97     if (MRI.use_empty(VReg))
     98       continue;
     99     // Handle stackified registers.
    100     if (MFI.isVRegStackified(VReg)) {
    101       DEBUG(dbgs() << "VReg " << VReg << " -> WAReg "
    102                    << (INT32_MIN | NumStackRegs) << "\n");
    103       MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++);
    104       continue;
    105     }
    106     if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) {
    107       DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n");
    108       MFI.setWAReg(VReg, CurReg++);
    109     }
    110   }
    111 
    112   return true;
    113 }
    114