1292915Sdim//===-- WebAssemblyRegNumbering.cpp - Register Numbering ------------------===// 2292915Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292915Sdim// 7292915Sdim//===----------------------------------------------------------------------===// 8292915Sdim/// 9292915Sdim/// \file 10341825Sdim/// This file implements a pass which assigns WebAssembly register 11292915Sdim/// numbers for CodeGen virtual registers. 12292915Sdim/// 13292915Sdim//===----------------------------------------------------------------------===// 14292915Sdim 15321369Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 16292915Sdim#include "WebAssembly.h" 17292915Sdim#include "WebAssemblyMachineFunctionInfo.h" 18292915Sdim#include "WebAssemblySubtarget.h" 19314564Sdim#include "WebAssemblyUtilities.h" 20292915Sdim#include "llvm/ADT/SCCIterator.h" 21309124Sdim#include "llvm/CodeGen/MachineFrameInfo.h" 22292915Sdim#include "llvm/CodeGen/MachineFunction.h" 23292915Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 24292915Sdim#include "llvm/CodeGen/MachineLoopInfo.h" 25292915Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 26292915Sdim#include "llvm/CodeGen/Passes.h" 27292915Sdim#include "llvm/Support/Debug.h" 28292915Sdim#include "llvm/Support/raw_ostream.h" 29292915Sdimusing namespace llvm; 30292915Sdim 31292915Sdim#define DEBUG_TYPE "wasm-reg-numbering" 32292915Sdim 33292915Sdimnamespace { 34292915Sdimclass WebAssemblyRegNumbering final : public MachineFunctionPass { 35314564Sdim StringRef getPassName() const override { 36292915Sdim return "WebAssembly Register Numbering"; 37292915Sdim } 38292915Sdim 39292915Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 40292915Sdim AU.setPreservesCFG(); 41292915Sdim MachineFunctionPass::getAnalysisUsage(AU); 42292915Sdim } 43292915Sdim 44292915Sdim bool runOnMachineFunction(MachineFunction &MF) override; 45292915Sdim 46292915Sdimpublic: 47292915Sdim static char ID; // Pass identification, replacement for typeid 48292915Sdim WebAssemblyRegNumbering() : MachineFunctionPass(ID) {} 49292915Sdim}; 50292915Sdim} // end anonymous namespace 51292915Sdim 52292915Sdimchar WebAssemblyRegNumbering::ID = 0; 53341825SdimINITIALIZE_PASS(WebAssemblyRegNumbering, DEBUG_TYPE, 54341825Sdim "Assigns WebAssembly register numbers for virtual registers", 55341825Sdim false, false) 56341825Sdim 57292915SdimFunctionPass *llvm::createWebAssemblyRegNumbering() { 58292915Sdim return new WebAssemblyRegNumbering(); 59292915Sdim} 60292915Sdim 61292915Sdimbool WebAssemblyRegNumbering::runOnMachineFunction(MachineFunction &MF) { 62341825Sdim LLVM_DEBUG(dbgs() << "********** Register Numbering **********\n" 63341825Sdim "********** Function: " 64341825Sdim << MF.getName() << '\n'); 65292915Sdim 66292915Sdim WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 67292915Sdim MachineRegisterInfo &MRI = MF.getRegInfo(); 68292915Sdim 69292915Sdim MFI.initWARegs(); 70292915Sdim 71292915Sdim // WebAssembly argument registers are in the same index space as local 72292915Sdim // variables. Assign the numbers for them first. 73292915Sdim MachineBasicBlock &EntryMBB = MF.front(); 74292915Sdim for (MachineInstr &MI : EntryMBB) { 75353358Sdim if (!WebAssembly::isArgument(MI.getOpcode())) 76292915Sdim break; 77314564Sdim 78314564Sdim int64_t Imm = MI.getOperand(1).getImm(); 79341825Sdim LLVM_DEBUG(dbgs() << "Arg VReg " << MI.getOperand(0).getReg() 80341825Sdim << " -> WAReg " << Imm << "\n"); 81314564Sdim MFI.setWAReg(MI.getOperand(0).getReg(), Imm); 82292915Sdim } 83292915Sdim 84292915Sdim // Then assign regular WebAssembly registers for all remaining used 85292915Sdim // virtual registers. TODO: Consider sorting the registers by frequency of 86292915Sdim // use, to maximize usage of small immediate fields. 87292915Sdim unsigned NumVRegs = MF.getRegInfo().getNumVirtRegs(); 88292915Sdim unsigned NumStackRegs = 0; 89309124Sdim // Start the numbering for locals after the arg regs 90309124Sdim unsigned CurReg = MFI.getParams().size(); 91292915Sdim for (unsigned VRegIdx = 0; VRegIdx < NumVRegs; ++VRegIdx) { 92360784Sdim unsigned VReg = Register::index2VirtReg(VRegIdx); 93309124Sdim // Skip unused registers. 94309124Sdim if (MRI.use_empty(VReg)) 95309124Sdim continue; 96292915Sdim // Handle stackified registers. 97292915Sdim if (MFI.isVRegStackified(VReg)) { 98341825Sdim LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " 99341825Sdim << (INT32_MIN | NumStackRegs) << "\n"); 100292915Sdim MFI.setWAReg(VReg, INT32_MIN | NumStackRegs++); 101292915Sdim continue; 102292915Sdim } 103309124Sdim if (MFI.getWAReg(VReg) == WebAssemblyFunctionInfo::UnusedReg) { 104341825Sdim LLVM_DEBUG(dbgs() << "VReg " << VReg << " -> WAReg " << CurReg << "\n"); 105309124Sdim MFI.setWAReg(VReg, CurReg++); 106309124Sdim } 107292915Sdim } 108292915Sdim 109292915Sdim return true; 110292915Sdim} 111