13ca95b02SDimitry Andric //===- WebAssemblyPrepareForLiveIntervals.cpp - Prepare for LiveIntervals -===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric ///
103ca95b02SDimitry Andric /// \file
114ba319b5SDimitry Andric /// Fix up code to meet LiveInterval's requirements.
123ca95b02SDimitry Andric ///
133ca95b02SDimitry Andric /// Some CodeGen passes don't preserve LiveInterval's requirements, because
143ca95b02SDimitry Andric /// they run after register allocation and it isn't important. However,
153ca95b02SDimitry Andric /// WebAssembly runs LiveIntervals in a late pass. This pass transforms code
163ca95b02SDimitry Andric /// to meet LiveIntervals' requirements; primarily, it ensures that all
173ca95b02SDimitry Andric /// virtual register uses have definitions (IMPLICIT_DEF definitions if
183ca95b02SDimitry Andric /// nothing else).
193ca95b02SDimitry Andric ///
203ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
213ca95b02SDimitry Andric 
223ca95b02SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
23db17bf38SDimitry Andric #include "WebAssembly.h"
243ca95b02SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
253ca95b02SDimitry Andric #include "WebAssemblySubtarget.h"
26d88c1a5aSDimitry Andric #include "WebAssemblyUtilities.h"
273ca95b02SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
283ca95b02SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
293ca95b02SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
303ca95b02SDimitry Andric #include "llvm/CodeGen/Passes.h"
313ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
323ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
333ca95b02SDimitry Andric using namespace llvm;
343ca95b02SDimitry Andric 
353ca95b02SDimitry Andric #define DEBUG_TYPE "wasm-prepare-for-live-intervals"
363ca95b02SDimitry Andric 
373ca95b02SDimitry Andric namespace {
383ca95b02SDimitry Andric class WebAssemblyPrepareForLiveIntervals final : public MachineFunctionPass {
393ca95b02SDimitry Andric public:
403ca95b02SDimitry Andric   static char ID; // Pass identification, replacement for typeid
WebAssemblyPrepareForLiveIntervals()413ca95b02SDimitry Andric   WebAssemblyPrepareForLiveIntervals() : MachineFunctionPass(ID) {}
423ca95b02SDimitry Andric 
433ca95b02SDimitry Andric private:
getPassName() const44d88c1a5aSDimitry Andric   StringRef getPassName() const override {
453ca95b02SDimitry Andric     return "WebAssembly Prepare For LiveIntervals";
463ca95b02SDimitry Andric   }
473ca95b02SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const483ca95b02SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
493ca95b02SDimitry Andric     AU.setPreservesCFG();
503ca95b02SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
513ca95b02SDimitry Andric   }
523ca95b02SDimitry Andric 
533ca95b02SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
543ca95b02SDimitry Andric };
553ca95b02SDimitry Andric } // end anonymous namespace
563ca95b02SDimitry Andric 
573ca95b02SDimitry Andric char WebAssemblyPrepareForLiveIntervals::ID = 0;
584ba319b5SDimitry Andric INITIALIZE_PASS(WebAssemblyPrepareForLiveIntervals, DEBUG_TYPE,
594ba319b5SDimitry Andric                 "Fix up code for LiveIntervals", false, false)
604ba319b5SDimitry Andric 
createWebAssemblyPrepareForLiveIntervals()613ca95b02SDimitry Andric FunctionPass *llvm::createWebAssemblyPrepareForLiveIntervals() {
623ca95b02SDimitry Andric   return new WebAssemblyPrepareForLiveIntervals();
633ca95b02SDimitry Andric }
643ca95b02SDimitry Andric 
653ca95b02SDimitry Andric // Test whether the given register has an ARGUMENT def.
HasArgumentDef(unsigned Reg,const MachineRegisterInfo & MRI)663ca95b02SDimitry Andric static bool HasArgumentDef(unsigned Reg, const MachineRegisterInfo &MRI) {
67d88c1a5aSDimitry Andric   for (const auto &Def : MRI.def_instructions(Reg))
68d88c1a5aSDimitry Andric     if (WebAssembly::isArgument(Def))
693ca95b02SDimitry Andric       return true;
703ca95b02SDimitry Andric   return false;
713ca95b02SDimitry Andric }
723ca95b02SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)73*b5893f02SDimitry Andric bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(
74*b5893f02SDimitry Andric     MachineFunction &MF) {
754ba319b5SDimitry Andric   LLVM_DEBUG({
763ca95b02SDimitry Andric     dbgs() << "********** Prepare For LiveIntervals **********\n"
773ca95b02SDimitry Andric            << "********** Function: " << MF.getName() << '\n';
783ca95b02SDimitry Andric   });
793ca95b02SDimitry Andric 
803ca95b02SDimitry Andric   bool Changed = false;
813ca95b02SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
823ca95b02SDimitry Andric   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
833ca95b02SDimitry Andric   MachineBasicBlock &Entry = *MF.begin();
843ca95b02SDimitry Andric 
853ca95b02SDimitry Andric   assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
863ca95b02SDimitry Andric          "LiveIntervals shouldn't be active yet!");
873ca95b02SDimitry Andric 
883ca95b02SDimitry Andric   // We don't preserve SSA form.
893ca95b02SDimitry Andric   MRI.leaveSSA();
903ca95b02SDimitry Andric 
913ca95b02SDimitry Andric   // BranchFolding and perhaps other passes don't preserve IMPLICIT_DEF
923ca95b02SDimitry Andric   // instructions. LiveIntervals requires that all paths to virtual register
933ca95b02SDimitry Andric   // uses provide a definition. Insert IMPLICIT_DEFs in the entry block to
943ca95b02SDimitry Andric   // conservatively satisfy this.
953ca95b02SDimitry Andric   //
963ca95b02SDimitry Andric   // TODO: This is fairly heavy-handed; find a better approach.
973ca95b02SDimitry Andric   //
983ca95b02SDimitry Andric   for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
993ca95b02SDimitry Andric     unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
1003ca95b02SDimitry Andric 
1013ca95b02SDimitry Andric     // Skip unused registers.
1023ca95b02SDimitry Andric     if (MRI.use_nodbg_empty(Reg))
1033ca95b02SDimitry Andric       continue;
1043ca95b02SDimitry Andric 
1053ca95b02SDimitry Andric     // Skip registers that have an ARGUMENT definition.
1063ca95b02SDimitry Andric     if (HasArgumentDef(Reg, MRI))
1073ca95b02SDimitry Andric       continue;
1083ca95b02SDimitry Andric 
1093ca95b02SDimitry Andric     BuildMI(Entry, Entry.begin(), DebugLoc(),
1103ca95b02SDimitry Andric             TII.get(WebAssembly::IMPLICIT_DEF), Reg);
1113ca95b02SDimitry Andric     Changed = true;
1123ca95b02SDimitry Andric   }
1133ca95b02SDimitry Andric 
1143ca95b02SDimitry Andric   // Move ARGUMENT_* instructions to the top of the entry block, so that their
1153ca95b02SDimitry Andric   // liveness reflects the fact that these really are live-in values.
1163ca95b02SDimitry Andric   for (auto MII = Entry.begin(), MIE = Entry.end(); MII != MIE;) {
117d88c1a5aSDimitry Andric     MachineInstr &MI = *MII++;
118d88c1a5aSDimitry Andric     if (WebAssembly::isArgument(MI)) {
119d88c1a5aSDimitry Andric       MI.removeFromParent();
120d88c1a5aSDimitry Andric       Entry.insert(Entry.begin(), &MI);
1213ca95b02SDimitry Andric     }
1223ca95b02SDimitry Andric   }
1233ca95b02SDimitry Andric 
1242cab237bSDimitry Andric   // Ok, we're now ready to run the LiveIntervals analysis again.
1253ca95b02SDimitry Andric   MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness);
1263ca95b02SDimitry Andric 
1273ca95b02SDimitry Andric   return Changed;
1283ca95b02SDimitry Andric }
129