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