1 | //===-- WebAssemblyReplacePhysRegs.cpp - Replace phys regs with virt regs -===// |
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 that replaces physical registers with |
11 | /// virtual registers. |
12 | /// |
13 | /// LLVM expects certain physical registers, such as a stack pointer. However, |
14 | /// WebAssembly doesn't actually have such physical registers. This pass is run |
15 | /// once LLVM no longer needs these registers, and replaces them with virtual |
16 | /// registers, so they can participate in register stackifying and coloring in |
17 | /// the normal way. |
18 | /// |
19 | //===----------------------------------------------------------------------===// |
20 | |
21 | #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" |
22 | #include "WebAssembly.h" |
23 | #include "WebAssemblyMachineFunctionInfo.h" |
24 | #include "WebAssemblySubtarget.h" |
25 | #include "llvm/CodeGen/MachineFunctionPass.h" |
26 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
27 | #include "llvm/CodeGen/Passes.h" |
28 | #include "llvm/Support/Debug.h" |
29 | #include "llvm/Support/raw_ostream.h" |
30 | using namespace llvm; |
31 | |
32 | #define DEBUG_TYPE "wasm-replace-phys-regs" |
33 | |
34 | namespace { |
35 | class WebAssemblyReplacePhysRegs final : public MachineFunctionPass { |
36 | public: |
37 | static char ID; // Pass identification, replacement for typeid |
38 | WebAssemblyReplacePhysRegs() : MachineFunctionPass(ID) {} |
39 | |
40 | private: |
41 | StringRef getPassName() const override { |
42 | return "WebAssembly Replace Physical Registers" ; |
43 | } |
44 | |
45 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
46 | AU.setPreservesCFG(); |
47 | MachineFunctionPass::getAnalysisUsage(AU); |
48 | } |
49 | |
50 | bool runOnMachineFunction(MachineFunction &MF) override; |
51 | }; |
52 | } // end anonymous namespace |
53 | |
54 | char WebAssemblyReplacePhysRegs::ID = 0; |
55 | INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE, |
56 | "Replace physical registers with virtual registers" , false, |
57 | false) |
58 | |
59 | FunctionPass *llvm::createWebAssemblyReplacePhysRegs() { |
60 | return new WebAssemblyReplacePhysRegs(); |
61 | } |
62 | |
63 | bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) { |
64 | LLVM_DEBUG({ |
65 | dbgs() << "********** Replace Physical Registers **********\n" |
66 | << "********** Function: " << MF.getName() << '\n'; |
67 | }); |
68 | |
69 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
70 | auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo(); |
71 | bool Changed = false; |
72 | |
73 | assert(!mustPreserveAnalysisID(LiveIntervalsID) && |
74 | "LiveIntervals shouldn't be active yet!" ); |
75 | |
76 | for (unsigned PReg = WebAssembly::NoRegister + 1; |
77 | PReg < WebAssembly::NUM_TARGET_REGS; ++PReg) { |
78 | // Skip fake registers that are never used explicitly. |
79 | if (PReg == WebAssembly::VALUE_STACK || PReg == WebAssembly::ARGUMENTS) |
80 | continue; |
81 | |
82 | // Replace explicit uses of the physical register with a virtual register. |
83 | const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg: PReg); |
84 | unsigned VReg = WebAssembly::NoRegister; |
85 | for (MachineOperand &MO : |
86 | llvm::make_early_inc_range(Range: MRI.reg_operands(Reg: PReg))) { |
87 | if (!MO.isImplicit()) { |
88 | if (VReg == WebAssembly::NoRegister) { |
89 | VReg = MRI.createVirtualRegister(RegClass: RC); |
90 | if (PReg == TRI.getFrameRegister(MF)) { |
91 | auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); |
92 | assert(!FI->isFrameBaseVirtual()); |
93 | FI->setFrameBaseVreg(VReg); |
94 | LLVM_DEBUG({ |
95 | dbgs() << "replacing preg " << PReg << " with " << VReg << " (" |
96 | << Register::virtReg2Index(VReg) << ")\n" ; |
97 | }); |
98 | } |
99 | } |
100 | MO.setReg(VReg); |
101 | Changed = true; |
102 | } |
103 | } |
104 | } |
105 | |
106 | return Changed; |
107 | } |
108 | |