1292915Sdim//===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===// 2292915Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292915Sdim// 7292915Sdim//===----------------------------------------------------------------------===// 8292915Sdim/// 9292915Sdim/// \file 10341825Sdim/// This file moves ARGUMENT instructions after ScheduleDAG scheduling. 11292915Sdim/// 12292915Sdim/// Arguments are really live-in registers, however, since we use virtual 13292915Sdim/// registers and LLVM doesn't support live-in virtual registers, we're 14292915Sdim/// currently making do with ARGUMENT instructions which are placed at the top 15292915Sdim/// of the entry block. The trick is to get them to *stay* at the top of the 16292915Sdim/// entry block. 17292915Sdim/// 18292915Sdim/// The ARGUMENTS physical register keeps these instructions pinned in place 19292915Sdim/// during liveness-aware CodeGen passes, however one thing which does not 20292915Sdim/// respect this is the ScheduleDAG scheduler. This pass is therefore run 21292915Sdim/// immediately after that. 22292915Sdim/// 23292915Sdim/// This is all hopefully a temporary solution until we find a better solution 24292915Sdim/// for describing the live-in nature of arguments. 25292915Sdim/// 26292915Sdim//===----------------------------------------------------------------------===// 27292915Sdim 28314564Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 29292915Sdim#include "WebAssembly.h" 30292915Sdim#include "WebAssemblyMachineFunctionInfo.h" 31314564Sdim#include "WebAssemblySubtarget.h" 32314564Sdim#include "WebAssemblyUtilities.h" 33292915Sdim#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 34292915Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 35292915Sdim#include "llvm/CodeGen/Passes.h" 36292915Sdim#include "llvm/Support/Debug.h" 37292915Sdim#include "llvm/Support/raw_ostream.h" 38292915Sdimusing namespace llvm; 39292915Sdim 40292915Sdim#define DEBUG_TYPE "wasm-argument-move" 41292915Sdim 42292915Sdimnamespace { 43292915Sdimclass WebAssemblyArgumentMove final : public MachineFunctionPass { 44292915Sdimpublic: 45292915Sdim static char ID; // Pass identification, replacement for typeid 46292915Sdim WebAssemblyArgumentMove() : MachineFunctionPass(ID) {} 47292915Sdim 48314564Sdim StringRef getPassName() const override { return "WebAssembly Argument Move"; } 49292915Sdim 50292915Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 51292915Sdim AU.setPreservesCFG(); 52292915Sdim AU.addPreserved<MachineBlockFrequencyInfo>(); 53292915Sdim AU.addPreservedID(MachineDominatorsID); 54292915Sdim MachineFunctionPass::getAnalysisUsage(AU); 55292915Sdim } 56292915Sdim 57292915Sdim bool runOnMachineFunction(MachineFunction &MF) override; 58292915Sdim}; 59292915Sdim} // end anonymous namespace 60292915Sdim 61292915Sdimchar WebAssemblyArgumentMove::ID = 0; 62341825SdimINITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE, 63341825Sdim "Move ARGUMENT instructions for WebAssembly", false, false) 64341825Sdim 65292915SdimFunctionPass *llvm::createWebAssemblyArgumentMove() { 66292915Sdim return new WebAssemblyArgumentMove(); 67292915Sdim} 68292915Sdim 69292915Sdimbool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) { 70341825Sdim LLVM_DEBUG({ 71292915Sdim dbgs() << "********** Argument Move **********\n" 72292915Sdim << "********** Function: " << MF.getName() << '\n'; 73292915Sdim }); 74292915Sdim 75292915Sdim bool Changed = false; 76292915Sdim MachineBasicBlock &EntryMBB = MF.front(); 77292915Sdim MachineBasicBlock::iterator InsertPt = EntryMBB.end(); 78292915Sdim 79292915Sdim // Look for the first NonArg instruction. 80309124Sdim for (MachineInstr &MI : EntryMBB) { 81353358Sdim if (!WebAssembly::isArgument(MI.getOpcode())) { 82309124Sdim InsertPt = MI; 83292915Sdim break; 84292915Sdim } 85292915Sdim } 86292915Sdim 87292915Sdim // Now move any argument instructions later in the block 88292915Sdim // to before our first NonArg instruction. 89309124Sdim for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) { 90353358Sdim if (WebAssembly::isArgument(MI.getOpcode())) { 91309124Sdim EntryMBB.insert(InsertPt, MI.removeFromParent()); 92292915Sdim Changed = true; 93292915Sdim } 94292915Sdim } 95292915Sdim 96292915Sdim return Changed; 97292915Sdim} 98