1*0b57cec5SDimitry Andric //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric /// 9*0b57cec5SDimitry Andric /// \file 10*0b57cec5SDimitry Andric /// This file moves ARGUMENT instructions after ScheduleDAG scheduling. 11*0b57cec5SDimitry Andric /// 12*0b57cec5SDimitry Andric /// Arguments are really live-in registers, however, since we use virtual 13*0b57cec5SDimitry Andric /// registers and LLVM doesn't support live-in virtual registers, we're 14*0b57cec5SDimitry Andric /// currently making do with ARGUMENT instructions which are placed at the top 15*0b57cec5SDimitry Andric /// of the entry block. The trick is to get them to *stay* at the top of the 16*0b57cec5SDimitry Andric /// entry block. 17*0b57cec5SDimitry Andric /// 18*0b57cec5SDimitry Andric /// The ARGUMENTS physical register keeps these instructions pinned in place 19*0b57cec5SDimitry Andric /// during liveness-aware CodeGen passes, however one thing which does not 20*0b57cec5SDimitry Andric /// respect this is the ScheduleDAG scheduler. This pass is therefore run 21*0b57cec5SDimitry Andric /// immediately after that. 22*0b57cec5SDimitry Andric /// 23*0b57cec5SDimitry Andric /// This is all hopefully a temporary solution until we find a better solution 24*0b57cec5SDimitry Andric /// for describing the live-in nature of arguments. 25*0b57cec5SDimitry Andric /// 26*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 29*0b57cec5SDimitry Andric #include "WebAssembly.h" 30*0b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 31*0b57cec5SDimitry Andric #include "WebAssemblySubtarget.h" 32*0b57cec5SDimitry Andric #include "WebAssemblyUtilities.h" 33*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 34*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 35*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 36*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 37*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 38*0b57cec5SDimitry Andric using namespace llvm; 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-argument-move" 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric namespace { 43*0b57cec5SDimitry Andric class WebAssemblyArgumentMove final : public MachineFunctionPass { 44*0b57cec5SDimitry Andric public: 45*0b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 46*0b57cec5SDimitry Andric WebAssemblyArgumentMove() : MachineFunctionPass(ID) {} 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric StringRef getPassName() const override { return "WebAssembly Argument Move"; } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 51*0b57cec5SDimitry Andric AU.setPreservesCFG(); 52*0b57cec5SDimitry Andric AU.addPreserved<MachineBlockFrequencyInfo>(); 53*0b57cec5SDimitry Andric AU.addPreservedID(MachineDominatorsID); 54*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 58*0b57cec5SDimitry Andric }; 59*0b57cec5SDimitry Andric } // end anonymous namespace 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric char WebAssemblyArgumentMove::ID = 0; 62*0b57cec5SDimitry Andric INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE, 63*0b57cec5SDimitry Andric "Move ARGUMENT instructions for WebAssembly", false, false) 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric FunctionPass *llvm::createWebAssemblyArgumentMove() { 66*0b57cec5SDimitry Andric return new WebAssemblyArgumentMove(); 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) { 70*0b57cec5SDimitry Andric LLVM_DEBUG({ 71*0b57cec5SDimitry Andric dbgs() << "********** Argument Move **********\n" 72*0b57cec5SDimitry Andric << "********** Function: " << MF.getName() << '\n'; 73*0b57cec5SDimitry Andric }); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric bool Changed = false; 76*0b57cec5SDimitry Andric MachineBasicBlock &EntryMBB = MF.front(); 77*0b57cec5SDimitry Andric MachineBasicBlock::iterator InsertPt = EntryMBB.end(); 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric // Look for the first NonArg instruction. 80*0b57cec5SDimitry Andric for (MachineInstr &MI : EntryMBB) { 81*0b57cec5SDimitry Andric if (!WebAssembly::isArgument(MI.getOpcode())) { 82*0b57cec5SDimitry Andric InsertPt = MI; 83*0b57cec5SDimitry Andric break; 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric // Now move any argument instructions later in the block 88*0b57cec5SDimitry Andric // to before our first NonArg instruction. 89*0b57cec5SDimitry Andric for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) { 90*0b57cec5SDimitry Andric if (WebAssembly::isArgument(MI.getOpcode())) { 91*0b57cec5SDimitry Andric EntryMBB.insert(InsertPt, MI.removeFromParent()); 92*0b57cec5SDimitry Andric Changed = true; 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric return Changed; 97*0b57cec5SDimitry Andric } 98