1 | //===--- WebAssemblyOptimizeLiveIntervals.cpp - LiveInterval processing ---===// |
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 | /// Optimize LiveIntervals for use in a post-RA context. |
11 | // |
12 | /// LiveIntervals normally runs before register allocation when the code is |
13 | /// only recently lowered out of SSA form, so it's uncommon for registers to |
14 | /// have multiple defs, and when they do, the defs are usually closely related. |
15 | /// Later, after coalescing, tail duplication, and other optimizations, it's |
16 | /// more common to see registers with multiple unrelated defs. This pass |
17 | /// updates LiveIntervals to distribute the value numbers across separate |
18 | /// LiveIntervals. |
19 | /// |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | #include "WebAssembly.h" |
23 | #include "WebAssemblyMachineFunctionInfo.h" |
24 | #include "WebAssemblySubtarget.h" |
25 | #include "llvm/CodeGen/LiveIntervals.h" |
26 | #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" |
27 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
28 | #include "llvm/CodeGen/Passes.h" |
29 | #include "llvm/Support/Debug.h" |
30 | #include "llvm/Support/raw_ostream.h" |
31 | using namespace llvm; |
32 | |
33 | #define DEBUG_TYPE "wasm-optimize-live-intervals" |
34 | |
35 | namespace { |
36 | class WebAssemblyOptimizeLiveIntervals final : public MachineFunctionPass { |
37 | StringRef getPassName() const override { |
38 | return "WebAssembly Optimize Live Intervals" ; |
39 | } |
40 | |
41 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
42 | AU.setPreservesCFG(); |
43 | AU.addRequired<LiveIntervalsWrapperPass>(); |
44 | AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>(); |
45 | AU.addPreserved<SlotIndexesWrapperPass>(); |
46 | AU.addPreserved<LiveIntervalsWrapperPass>(); |
47 | AU.addPreservedID(ID&: LiveVariablesID); |
48 | AU.addPreservedID(ID&: MachineDominatorsID); |
49 | MachineFunctionPass::getAnalysisUsage(AU); |
50 | } |
51 | |
52 | MachineFunctionProperties getRequiredProperties() const override { |
53 | return MachineFunctionProperties().setTracksLiveness(); |
54 | } |
55 | |
56 | bool runOnMachineFunction(MachineFunction &MF) override; |
57 | |
58 | public: |
59 | static char ID; // Pass identification, replacement for typeid |
60 | WebAssemblyOptimizeLiveIntervals() : MachineFunctionPass(ID) {} |
61 | }; |
62 | } // end anonymous namespace |
63 | |
64 | char WebAssemblyOptimizeLiveIntervals::ID = 0; |
65 | INITIALIZE_PASS(WebAssemblyOptimizeLiveIntervals, DEBUG_TYPE, |
66 | "Optimize LiveIntervals for WebAssembly" , false, false) |
67 | |
68 | FunctionPass *llvm::createWebAssemblyOptimizeLiveIntervals() { |
69 | return new WebAssemblyOptimizeLiveIntervals(); |
70 | } |
71 | |
72 | bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction( |
73 | MachineFunction &MF) { |
74 | LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n" |
75 | "********** Function: " |
76 | << MF.getName() << '\n'); |
77 | |
78 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
79 | auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS(); |
80 | |
81 | // We don't preserve SSA form. |
82 | MRI.leaveSSA(); |
83 | |
84 | assert(MRI.tracksLiveness() && "OptimizeLiveIntervals expects liveness" ); |
85 | |
86 | // Split multiple-VN LiveIntervals into multiple LiveIntervals. |
87 | SmallVector<LiveInterval *, 4> SplitLIs; |
88 | for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) { |
89 | Register Reg = Register::index2VirtReg(Index: I); |
90 | auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo(); |
91 | |
92 | if (MRI.reg_nodbg_empty(RegNo: Reg)) |
93 | continue; |
94 | |
95 | LIS.splitSeparateComponents(LI&: LIS.getInterval(Reg), SplitLIs); |
96 | if (Reg == TRI.getFrameRegister(MF) && SplitLIs.size() > 0) { |
97 | // The live interval for the frame register was split, resulting in a new |
98 | // VReg. For now we only support debug info output for a single frame base |
99 | // value for the function, so just use the last one. It will certainly be |
100 | // wrong for some part of the function, but until we are able to track |
101 | // values through live-range splitting and stackification, it will have to |
102 | // do. |
103 | MF.getInfo<WebAssemblyFunctionInfo>()->setFrameBaseVreg( |
104 | SplitLIs.back()->reg()); |
105 | } |
106 | SplitLIs.clear(); |
107 | } |
108 | |
109 | // In FixIrreducibleControlFlow, we conservatively inserted IMPLICIT_DEF |
110 | // instructions to satisfy LiveIntervals' requirement that all uses be |
111 | // dominated by defs. Now that LiveIntervals has computed which of these |
112 | // defs are actually needed and which are dead, remove the dead ones. |
113 | for (MachineInstr &MI : llvm::make_early_inc_range(Range&: MF.front())) { |
114 | if (MI.isImplicitDef() && MI.getOperand(i: 0).isDead()) { |
115 | LiveInterval &LI = LIS.getInterval(Reg: MI.getOperand(i: 0).getReg()); |
116 | LIS.removeVRegDefAt(LI, Pos: LIS.getInstructionIndex(Instr: MI).getRegSlot()); |
117 | LIS.RemoveMachineInstrFromMaps(MI); |
118 | MI.eraseFromParent(); |
119 | } |
120 | } |
121 | |
122 | return true; |
123 | } |
124 | |