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