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