|  | //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// This file moves ARGUMENT instructions after ScheduleDAG scheduling. | 
|  | /// | 
|  | /// Arguments are really live-in registers, however, since we use virtual | 
|  | /// registers and LLVM doesn't support live-in virtual registers, we're | 
|  | /// currently making do with ARGUMENT instructions which are placed at the top | 
|  | /// of the entry block. The trick is to get them to *stay* at the top of the | 
|  | /// entry block. | 
|  | /// | 
|  | /// The ARGUMENTS physical register keeps these instructions pinned in place | 
|  | /// during liveness-aware CodeGen passes, however one thing which does not | 
|  | /// respect this is the ScheduleDAG scheduler. This pass is therefore run | 
|  | /// immediately after that. | 
|  | /// | 
|  | /// This is all hopefully a temporary solution until we find a better solution | 
|  | /// for describing the live-in nature of arguments. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" | 
|  | #include "WebAssembly.h" | 
|  | #include "WebAssemblyMachineFunctionInfo.h" | 
|  | #include "WebAssemblySubtarget.h" | 
|  | #include "WebAssemblyUtilities.h" | 
|  | #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" | 
|  | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | #include "llvm/CodeGen/Passes.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "wasm-argument-move" | 
|  |  | 
|  | namespace { | 
|  | class WebAssemblyArgumentMove final : public MachineFunctionPass { | 
|  | public: | 
|  | static char ID; // Pass identification, replacement for typeid | 
|  | WebAssemblyArgumentMove() : MachineFunctionPass(ID) {} | 
|  |  | 
|  | StringRef getPassName() const override { return "WebAssembly Argument Move"; } | 
|  |  | 
|  | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
|  | AU.setPreservesCFG(); | 
|  | AU.addPreserved<MachineBlockFrequencyInfo>(); | 
|  | AU.addPreservedID(MachineDominatorsID); | 
|  | MachineFunctionPass::getAnalysisUsage(AU); | 
|  | } | 
|  |  | 
|  | bool runOnMachineFunction(MachineFunction &MF) override; | 
|  | }; | 
|  | } // end anonymous namespace | 
|  |  | 
|  | char WebAssemblyArgumentMove::ID = 0; | 
|  | INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE, | 
|  | "Move ARGUMENT instructions for WebAssembly", false, false) | 
|  |  | 
|  | FunctionPass *llvm::createWebAssemblyArgumentMove() { | 
|  | return new WebAssemblyArgumentMove(); | 
|  | } | 
|  |  | 
|  | bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "********** Argument Move **********\n" | 
|  | << "********** Function: " << MF.getName() << '\n'; | 
|  | }); | 
|  |  | 
|  | bool Changed = false; | 
|  | MachineBasicBlock &EntryMBB = MF.front(); | 
|  | MachineBasicBlock::iterator InsertPt = EntryMBB.end(); | 
|  |  | 
|  | // Look for the first NonArg instruction. | 
|  | for (MachineInstr &MI : EntryMBB) { | 
|  | if (!WebAssembly::isArgument(MI.getOpcode())) { | 
|  | InsertPt = MI; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Now move any argument instructions later in the block | 
|  | // to before our first NonArg instruction. | 
|  | for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) { | 
|  | if (WebAssembly::isArgument(MI.getOpcode())) { | 
|  | EntryMBB.insert(InsertPt, MI.removeFromParent()); | 
|  | Changed = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | return Changed; | 
|  | } |