10cfb5f85SDan Gohman //===--- WebAssemblyOptimizeLiveIntervals.cpp - LiveInterval processing ---===//
20cfb5f85SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60cfb5f85SDan Gohman //
70cfb5f85SDan Gohman //===----------------------------------------------------------------------===//
80cfb5f85SDan Gohman ///
90cfb5f85SDan Gohman /// \file
105f8f34e4SAdrian Prantl /// Optimize LiveIntervals for use in a post-RA context.
110cfb5f85SDan Gohman //
120cfb5f85SDan Gohman /// LiveIntervals normally runs before register allocation when the code is
130cfb5f85SDan Gohman /// only recently lowered out of SSA form, so it's uncommon for registers to
14fd2f7aebSDan Gohman /// have multiple defs, and when they do, the defs are usually closely related.
150cfb5f85SDan Gohman /// Later, after coalescing, tail duplication, and other optimizations, it's
160cfb5f85SDan Gohman /// more common to see registers with multiple unrelated defs. This pass
17f842297dSMatthias Braun /// updates LiveIntervals to distribute the value numbers across separate
180cfb5f85SDan Gohman /// LiveIntervals.
190cfb5f85SDan Gohman ///
200cfb5f85SDan Gohman //===----------------------------------------------------------------------===//
210cfb5f85SDan Gohman
220cfb5f85SDan Gohman #include "WebAssembly.h"
23ff171acfSDerek Schuff #include "WebAssemblyMachineFunctionInfo.h"
240cfb5f85SDan Gohman #include "WebAssemblySubtarget.h"
25f842297dSMatthias Braun #include "llvm/CodeGen/LiveIntervals.h"
260cfb5f85SDan Gohman #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
270cfb5f85SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
280cfb5f85SDan Gohman #include "llvm/CodeGen/Passes.h"
290cfb5f85SDan Gohman #include "llvm/Support/Debug.h"
300cfb5f85SDan Gohman #include "llvm/Support/raw_ostream.h"
310cfb5f85SDan Gohman using namespace llvm;
320cfb5f85SDan Gohman
330cfb5f85SDan Gohman #define DEBUG_TYPE "wasm-optimize-live-intervals"
340cfb5f85SDan Gohman
350cfb5f85SDan Gohman namespace {
360cfb5f85SDan Gohman class WebAssemblyOptimizeLiveIntervals final : public MachineFunctionPass {
getPassName() const37117296c0SMehdi Amini StringRef getPassName() const override {
380cfb5f85SDan Gohman return "WebAssembly Optimize Live Intervals";
390cfb5f85SDan Gohman }
400cfb5f85SDan Gohman
getAnalysisUsage(AnalysisUsage & AU) const410cfb5f85SDan Gohman void getAnalysisUsage(AnalysisUsage &AU) const override {
420cfb5f85SDan Gohman AU.setPreservesCFG();
430cfb5f85SDan Gohman AU.addRequired<LiveIntervals>();
440cfb5f85SDan Gohman AU.addPreserved<MachineBlockFrequencyInfo>();
450cfb5f85SDan Gohman AU.addPreserved<SlotIndexes>();
460cfb5f85SDan Gohman AU.addPreserved<LiveIntervals>();
470cfb5f85SDan Gohman AU.addPreservedID(LiveVariablesID);
480cfb5f85SDan Gohman AU.addPreservedID(MachineDominatorsID);
490cfb5f85SDan Gohman MachineFunctionPass::getAnalysisUsage(AU);
500cfb5f85SDan Gohman }
510cfb5f85SDan Gohman
getRequiredProperties() const52*cde083e0SHeejin Ahn MachineFunctionProperties getRequiredProperties() const override {
53*cde083e0SHeejin Ahn return MachineFunctionProperties().set(
54*cde083e0SHeejin Ahn MachineFunctionProperties::Property::TracksLiveness);
55*cde083e0SHeejin Ahn }
56*cde083e0SHeejin Ahn
570cfb5f85SDan Gohman bool runOnMachineFunction(MachineFunction &MF) override;
580cfb5f85SDan Gohman
590cfb5f85SDan Gohman public:
600cfb5f85SDan Gohman static char ID; // Pass identification, replacement for typeid
WebAssemblyOptimizeLiveIntervals()610cfb5f85SDan Gohman WebAssemblyOptimizeLiveIntervals() : MachineFunctionPass(ID) {}
620cfb5f85SDan Gohman };
630cfb5f85SDan Gohman } // end anonymous namespace
640cfb5f85SDan Gohman
650cfb5f85SDan Gohman char WebAssemblyOptimizeLiveIntervals::ID = 0;
6640926451SJacob Gravelle INITIALIZE_PASS(WebAssemblyOptimizeLiveIntervals, DEBUG_TYPE,
6740926451SJacob Gravelle "Optimize LiveIntervals for WebAssembly", false, false)
6840926451SJacob Gravelle
createWebAssemblyOptimizeLiveIntervals()690cfb5f85SDan Gohman FunctionPass *llvm::createWebAssemblyOptimizeLiveIntervals() {
700cfb5f85SDan Gohman return new WebAssemblyOptimizeLiveIntervals();
710cfb5f85SDan Gohman }
720cfb5f85SDan Gohman
runOnMachineFunction(MachineFunction & MF)73f208f631SHeejin Ahn bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
74f208f631SHeejin Ahn MachineFunction &MF) {
75d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n"
760cfb5f85SDan Gohman "********** Function: "
770cfb5f85SDan Gohman << MF.getName() << '\n');
780cfb5f85SDan Gohman
790cfb5f85SDan Gohman MachineRegisterInfo &MRI = MF.getRegInfo();
8018c56a07SHeejin Ahn auto &LIS = getAnalysis<LiveIntervals>();
810cfb5f85SDan Gohman
820cfb5f85SDan Gohman // We don't preserve SSA form.
830cfb5f85SDan Gohman MRI.leaveSSA();
840cfb5f85SDan Gohman
85f208f631SHeejin Ahn assert(MRI.tracksLiveness() && "OptimizeLiveIntervals expects liveness");
860cfb5f85SDan Gohman
870cfb5f85SDan Gohman // Split multiple-VN LiveIntervals into multiple LiveIntervals.
880cfb5f85SDan Gohman SmallVector<LiveInterval *, 4> SplitLIs;
8918c56a07SHeejin Ahn for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
90d6b07348SJim Lin Register Reg = Register::index2VirtReg(I);
91ff171acfSDerek Schuff auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
92ff171acfSDerek Schuff
9380906d9dSDerek Schuff if (MRI.reg_nodbg_empty(Reg))
940cfb5f85SDan Gohman continue;
950cfb5f85SDan Gohman
960cfb5f85SDan Gohman LIS.splitSeparateComponents(LIS.getInterval(Reg), SplitLIs);
97ff171acfSDerek Schuff if (Reg == TRI.getFrameRegister(MF) && SplitLIs.size() > 0) {
98ff171acfSDerek Schuff // The live interval for the frame register was split, resulting in a new
99ff171acfSDerek Schuff // VReg. For now we only support debug info output for a single frame base
100ff171acfSDerek Schuff // value for the function, so just use the last one. It will certainly be
101ff171acfSDerek Schuff // wrong for some part of the function, but until we are able to track
102ff171acfSDerek Schuff // values through live-range splitting and stackification, it will have to
103ff171acfSDerek Schuff // do.
104ff171acfSDerek Schuff MF.getInfo<WebAssemblyFunctionInfo>()->setFrameBaseVreg(
1056e85c3d5SMircea Trofin SplitLIs.back()->reg());
106ff171acfSDerek Schuff }
1070cfb5f85SDan Gohman SplitLIs.clear();
1080cfb5f85SDan Gohman }
1090cfb5f85SDan Gohman
110*cde083e0SHeejin Ahn // In FixIrreducibleControlFlow, we conservatively inserted IMPLICIT_DEF
1110cfb5f85SDan Gohman // instructions to satisfy LiveIntervals' requirement that all uses be
1120cfb5f85SDan Gohman // dominated by defs. Now that LiveIntervals has computed which of these
1130cfb5f85SDan Gohman // defs are actually needed and which are dead, remove the dead ones.
11485b4b21cSKazu Hirata for (MachineInstr &MI : llvm::make_early_inc_range(MF.front())) {
11585b4b21cSKazu Hirata if (MI.isImplicitDef() && MI.getOperand(0).isDead()) {
11685b4b21cSKazu Hirata LiveInterval &LI = LIS.getInterval(MI.getOperand(0).getReg());
11785b4b21cSKazu Hirata LIS.removeVRegDefAt(LI, LIS.getInstructionIndex(MI).getRegSlot());
11885b4b21cSKazu Hirata LIS.RemoveMachineInstrFromMaps(MI);
11985b4b21cSKazu Hirata MI.eraseFromParent();
1200cfb5f85SDan Gohman }
1210cfb5f85SDan Gohman }
1220cfb5f85SDan Gohman
123ff171acfSDerek Schuff return true;
1240cfb5f85SDan Gohman }
125