1 //===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements a pass which assigns WebAssembly register 11 /// numbers for CodeGen virtual registers. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 16 #include "WebAssembly.h" 17 #include "WebAssemblyMachineFunctionInfo.h" 18 #include "WebAssemblySubtarget.h" 19 #include "WebAssemblyUtilities.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 StringRef 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 INITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE, 54 "Assigns WebAssembly register numbers for virtual registers", 55 false, false) 56 57 FunctionPass *llvm::createWebAssemblyRegNumbering() { 58 return new WebAssemblyRegNumbering(); 59 } 60 61 bool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) { 62 LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n" 63 "********** Function: " 64 << MF.getName() << '\n'); 65 66 WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 67 MachineRegisterInfo &MRI = MF.getRegInfo(); 68 69 MFI.initWARegs(MRI); 70 71 // WebAssembly argument registers are in the same index space as local 72 // variables. Assign the numbers for them first. 73 MachineBasicBlock &EntryMBB = MF.front(); 74 for (MachineInstr &MI : EntryMBB) { 75 if (!WebAssembly::isArgument(MI.getOpcode())) 76 break; 77 78 int64_t Imm = MI.getOperand(1).getImm(); 79 LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg() 80 << " -> WAReg " << Imm << "\n"); 81 MFI.setWAReg(MI.getOperand(0).getReg(), Imm); 82 } 83 84 // Then assign regular WebAssembly registers for all remaining used 85 // virtual registers. TODO: Consider sorting the registers by frequency of 86 // use, to maximize usage of small immediate fields. 87 unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs(); 88 unsigned NumStackRegs = 0; 89 // Start the numbering for locals after the arg regs 90 unsigned CurReg = MFI.getParams().size(); 91 for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) { 92 unsigned VReg = Register::index2VirtReg(VRegIdx); 93 // Skip unused registers. 94 if (MRI.use_empty(VReg)) 95 continue; 96 // Handle stackified registers. 97 if (MFI.isVRegStackified(VReg)) { 98 LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " 99 << (INT32_MIN | NumStackRegs) << "\n"); 100 MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++); 101 continue; 102 } 103 if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) { 104 LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n"); 105 MFI.setWAReg(VReg, CurReg++); 106 } 107 } 108 109 return true; 110 } 111