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