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 AndricFunctionPass *llvm::createWebAssemblyRegNumbering() { 597d523365SDimitry Andric return new WebAssemblyRegNumbering(); 607d523365SDimitry Andric } 617d523365SDimitry Andric runOnMachineFunction(MachineFunction & MF)627d523365SDimitry Andricbool 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