10b57cec5SDimitry Andric //===-- WebAssemblyReplacePhysRegs.cpp - Replace phys regs with virt regs -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements a pass that replaces physical registers with
110b57cec5SDimitry Andric /// virtual registers.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// LLVM expects certain physical registers, such as a stack pointer. However,
140b57cec5SDimitry Andric /// WebAssembly doesn't actually have such physical registers. This pass is run
150b57cec5SDimitry Andric /// once LLVM no longer needs these registers, and replaces them with virtual
160b57cec5SDimitry Andric /// registers, so they can participate in register stackifying and coloring in
170b57cec5SDimitry Andric /// the normal way.
180b57cec5SDimitry Andric ///
190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
220b57cec5SDimitry Andric #include "WebAssembly.h"
230b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
240b57cec5SDimitry Andric #include "WebAssemblySubtarget.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
280b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-replace-phys-regs"
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric namespace {
350b57cec5SDimitry Andric class WebAssemblyReplacePhysRegs final : public MachineFunctionPass {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid
WebAssemblyReplacePhysRegs()380b57cec5SDimitry Andric WebAssemblyReplacePhysRegs() : MachineFunctionPass(ID) {}
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric private:
getPassName() const410b57cec5SDimitry Andric StringRef getPassName() const override {
420b57cec5SDimitry Andric return "WebAssembly Replace Physical Registers";
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const450b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
460b57cec5SDimitry Andric AU.setPreservesCFG();
470b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
510b57cec5SDimitry Andric };
520b57cec5SDimitry Andric } // end anonymous namespace
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric char WebAssemblyReplacePhysRegs::ID = 0;
550b57cec5SDimitry Andric INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
560b57cec5SDimitry Andric "Replace physical registers with virtual registers", false,
570b57cec5SDimitry Andric false)
580b57cec5SDimitry Andric
createWebAssemblyReplacePhysRegs()590b57cec5SDimitry Andric FunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
600b57cec5SDimitry Andric return new WebAssemblyReplacePhysRegs();
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)630b57cec5SDimitry Andric bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
640b57cec5SDimitry Andric LLVM_DEBUG({
650b57cec5SDimitry Andric dbgs() << "********** Replace Physical Registers **********\n"
660b57cec5SDimitry Andric << "********** Function: " << MF.getName() << '\n';
670b57cec5SDimitry Andric });
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo();
705ffd83dbSDimitry Andric auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
710b57cec5SDimitry Andric bool Changed = false;
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
740b57cec5SDimitry Andric "LiveIntervals shouldn't be active yet!");
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric for (unsigned PReg = WebAssembly::NoRegister + 1;
770b57cec5SDimitry Andric PReg < WebAssembly::NUM_TARGET_REGS; ++PReg) {
780b57cec5SDimitry Andric // Skip fake registers that are never used explicitly.
790b57cec5SDimitry Andric if (PReg == WebAssembly::VALUE_STACK || PReg == WebAssembly::ARGUMENTS)
800b57cec5SDimitry Andric continue;
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric // Replace explicit uses of the physical register with a virtual register.
830b57cec5SDimitry Andric const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
840b57cec5SDimitry Andric unsigned VReg = WebAssembly::NoRegister;
85*349cc55cSDimitry Andric for (MachineOperand &MO :
86*349cc55cSDimitry Andric llvm::make_early_inc_range(MRI.reg_operands(PReg))) {
870b57cec5SDimitry Andric if (!MO.isImplicit()) {
885ffd83dbSDimitry Andric if (VReg == WebAssembly::NoRegister) {
890b57cec5SDimitry Andric VReg = MRI.createVirtualRegister(RC);
905ffd83dbSDimitry Andric if (PReg == TRI.getFrameRegister(MF)) {
915ffd83dbSDimitry Andric auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
925ffd83dbSDimitry Andric assert(!FI->isFrameBaseVirtual());
935ffd83dbSDimitry Andric FI->setFrameBaseVreg(VReg);
945ffd83dbSDimitry Andric LLVM_DEBUG({
955ffd83dbSDimitry Andric dbgs() << "replacing preg " << PReg << " with " << VReg << " ("
965ffd83dbSDimitry Andric << Register::virtReg2Index(VReg) << ")\n";
975ffd83dbSDimitry Andric });
985ffd83dbSDimitry Andric }
995ffd83dbSDimitry Andric }
1000b57cec5SDimitry Andric MO.setReg(VReg);
1010b57cec5SDimitry Andric Changed = true;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric return Changed;
1070b57cec5SDimitry Andric }
108