WebAssemblyArgumentMove.cpp revision 309124
1185029Spjd//===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===// 2185029Spjd// 3185029Spjd// The LLVM Compiler Infrastructure 4185029Spjd// 5185029Spjd// This file is distributed under the University of Illinois Open Source 6185029Spjd// License. See LICENSE.TXT for details. 7185029Spjd// 8185029Spjd//===----------------------------------------------------------------------===// 9185029Spjd/// 10185029Spjd/// \file 11185029Spjd/// \brief This file moves ARGUMENT instructions after ScheduleDAG scheduling. 12185029Spjd/// 13185029Spjd/// Arguments are really live-in registers, however, since we use virtual 14185029Spjd/// registers and LLVM doesn't support live-in virtual registers, we're 15185029Spjd/// currently making do with ARGUMENT instructions which are placed at the top 16185029Spjd/// of the entry block. The trick is to get them to *stay* at the top of the 17185029Spjd/// entry block. 18185029Spjd/// 19185029Spjd/// The ARGUMENTS physical register keeps these instructions pinned in place 20185029Spjd/// during liveness-aware CodeGen passes, however one thing which does not 21331396Smav/// respect this is the ScheduleDAG scheduler. This pass is therefore run 22185029Spjd/// immediately after that. 23219089Spjd/// 24331396Smav/// This is all hopefully a temporary solution until we find a better solution 25331397Smav/// for describing the live-in nature of arguments. 26185029Spjd/// 27185029Spjd//===----------------------------------------------------------------------===// 28185029Spjd 29185029Spjd#include "WebAssembly.h" 30185029Spjd#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 31185029Spjd#include "WebAssemblyMachineFunctionInfo.h" 32185029Spjd#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 33185029Spjd#include "llvm/CodeGen/MachineRegisterInfo.h" 34185029Spjd#include "llvm/CodeGen/Passes.h" 35185029Spjd#include "llvm/Support/Debug.h" 36185029Spjd#include "llvm/Support/raw_ostream.h" 37185029Spjdusing namespace llvm; 38185029Spjd 39185029Spjd#define DEBUG_TYPE "wasm-argument-move" 40185029Spjd 41185029Spjdnamespace { 42185029Spjdclass WebAssemblyArgumentMove final : public MachineFunctionPass { 43185029Spjdpublic: 44185029Spjd static char ID; // Pass identification, replacement for typeid 45185029Spjd WebAssemblyArgumentMove() : MachineFunctionPass(ID) {} 46185029Spjd 47185029Spjd const char *getPassName() const override { 48185029Spjd return "WebAssembly Argument Move"; 49185029Spjd } 50185029Spjd 51185029Spjd void getAnalysisUsage(AnalysisUsage &AU) const override { 52185029Spjd AU.setPreservesCFG(); 53185029Spjd AU.addPreserved<MachineBlockFrequencyInfo>(); 54185029Spjd AU.addPreservedID(MachineDominatorsID); 55185029Spjd MachineFunctionPass::getAnalysisUsage(AU); 56185029Spjd } 57219089Spjd 58185029Spjd bool runOnMachineFunction(MachineFunction &MF) override; 59185029Spjd}; 60185029Spjd} // end anonymous namespace 61185029Spjd 62185029Spjdchar WebAssemblyArgumentMove::ID = 0; 63185029SpjdFunctionPass *llvm::createWebAssemblyArgumentMove() { 64185029Spjd return new WebAssemblyArgumentMove(); 65185029Spjd} 66185029Spjd 67185029Spjd/// Test whether the given instruction is an ARGUMENT. 68185029Spjdstatic bool IsArgument(const MachineInstr &MI) { 69185029Spjd switch (MI.getOpcode()) { 70185029Spjd case WebAssembly::ARGUMENT_I32: 71185029Spjd case WebAssembly::ARGUMENT_I64: 72185029Spjd case WebAssembly::ARGUMENT_F32: 73185029Spjd case WebAssembly::ARGUMENT_F64: 74185029Spjd return true; 75185029Spjd default: 76185029Spjd return false; 77185029Spjd } 78185029Spjd} 79185029Spjd 80185029Spjdbool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) { 81185029Spjd DEBUG({ 82185029Spjd dbgs() << "********** Argument Move **********\n" 83185029Spjd << "********** Function: " << MF.getName() << '\n'; 84185029Spjd }); 85185029Spjd 86185029Spjd bool Changed = false; 87185029Spjd MachineBasicBlock &EntryMBB = MF.front(); 88185029Spjd MachineBasicBlock::iterator InsertPt = EntryMBB.end(); 89185029Spjd 90185029Spjd // Look for the first NonArg instruction. 91185029Spjd for (MachineInstr &MI : EntryMBB) { 92185029Spjd if (!IsArgument(MI)) { 93185029Spjd InsertPt = MI; 94185029Spjd break; 95185029Spjd } 96185029Spjd } 97185029Spjd 98185029Spjd // Now move any argument instructions later in the block 99185029Spjd // to before our first NonArg instruction. 100185029Spjd for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) { 101185029Spjd if (IsArgument(MI)) { 102185029Spjd EntryMBB.insert(InsertPt, MI.removeFromParent()); 103185029Spjd Changed = true; 104185029Spjd } 105185029Spjd } 106185029Spjd 107185029Spjd return Changed; 108185029Spjd} 109185029Spjd